Пример #1
0
def test_update_groups(database, tmpdir):
    """Test updating group name and group members."""
    # -- Setup ----------------------------------------------------------------
    #
    # Create a database with two groups for one workflow. Group 1 has user 1 as
    # only member, group 2 has user 2 and 3 as member.
    fs = FileSystemStorage(basedir=tmpdir)
    with database.session() as session:
        user_1 = model.create_user(session, active=True)
        user_2 = model.create_user(session, active=True)
        user_3 = model.create_user(session, active=True)
        workflow_id = model.create_workflow(session)
        members_1 = [user_1]
        group_1 = model.create_group(session, workflow_id, users=members_1)
        members_2 = [user_2, user_3]
        group_2 = model.create_group(session, workflow_id, users=members_2)
    # -- Test add member ------------------------------------------------------
    with database.session() as session:
        manager = WorkflowGroupManager(session=session, fs=fs)
        members_1 = [user_1, user_3]
        manager.update_group(group_1, members=members_1)
        members = [m.user_id for m in manager.get_group(group_1).members]
        assert set(members) == set(members_1)
        members = [m.user_id for m in manager.get_group(group_2).members]
        assert set(members) == set(members_2)
    # -- Test rename group ----------------------------------------------------
    with database.session() as session:
        manager = WorkflowGroupManager(session=session, fs=fs)
        manager.update_group(group_2, name='My Group')
        assert manager.get_group(group_1).name == group_1
        assert manager.get_group(group_2).name == 'My Group'
    # -- Test rename group and change members ---------------------------------
    with database.session() as session:
        manager = WorkflowGroupManager(session=session, fs=fs)
        members_2 = [user_1] + members_2
        manager.update_group(group_2, name='The Group', members=members_2)
        members = [m.user_id for m in manager.get_group(group_1).members]
        assert set(members) == set(members_1)
        members = [m.user_id for m in manager.get_group(group_2).members]
        assert set(members) == set(members_2)
        assert manager.get_group(group_1).name == group_1
        assert manager.get_group(group_2).name == 'The Group'
    # -- Test no changes ------------------------------------------------------
    with database.session() as session:
        manager = WorkflowGroupManager(session=session, fs=fs)
        manager.update_group(group_2, name='The Group', members=members_2)
        members = [m.user_id for m in manager.get_group(group_1).members]
        assert set(members) == set(members_1)
        members = [m.user_id for m in manager.get_group(group_2).members]
        assert set(members) == set(members_2)
        assert manager.get_group(group_1).name == group_1
        assert manager.get_group(group_2).name == 'The Group'
Пример #2
0
def test_access_run_result_files_local(database, tmpdir):
    """Test accessing run result files."""
    # -- Setup ----------------------------------------------------------------
    env = Config().basedir(tmpdir).auth()
    fs = FS(env=env)
    workflow_id, group_id, run_id, user_id = success_run(database, fs, tmpdir)
    local_service = LocalAPIFactory(env=env, db=database, engine=StateEngine())
    # -- Read result files ----------------------------------------------------
    with local_service(user_id=user_id) as api:
        # Map file names to file handles.
        r = api.runs().get_run(run_id=run_id)
        files = dict()
        for fh in r['files']:
            files[fh['name']] = fh['id']
        # Read content of result files.
        fh = api.runs().get_result_file(run_id=run_id,
                                        file_id=files['run/results/B.json'])
        results = util.read_object(fh.open())
        assert results == {'B': 1}
    # -- Error when user 2 attempts to read file ------------------------------
    with database.session() as session:
        user_2 = create_user(session, active=True)
    with local_service(user_id=user_2) as api:
        with pytest.raises(err.UnauthorizedAccessError):
            api.runs().get_result_file(run_id=run_id,
                                       file_id=files['run/results/B.json'])
    # -- With an open access policy user 2 can read the data file -------------
    env = Config().basedir(tmpdir).open_access()
    local_service = LocalAPIFactory(env=env, db=database, engine=StateEngine())
    with local_service(user_id=user_2) as api:
        api.runs().get_result_file(run_id=run_id,
                                   file_id=files['run/results/B.json'])
Пример #3
0
def test_list_files(database, tmpdir):
    """Test listing uploaded files."""
    # -- Setup ----------------------------------------------------------------
    #
    # Create a database with two groups for a single workflow. The first group
    # has one uploaded file and the second group has one file.
    fn = 'data.json'
    fs = FileSystemStorage(basedir=tmpdir)
    with database.session() as session:
        user_1 = model.create_user(session, active=True)
        workflow_id = model.create_workflow(session)
        group_1 = model.create_group(session, workflow_id, users=[user_1])
        group_2 = model.create_group(session, workflow_id, users=[user_1])
        manager = WorkflowGroupManager(session=session, fs=fs)
        manager.upload_file(group_id=group_1,
                            file=io_file(data={'A': 1}),
                            name=fn)
        manager.upload_file(group_id=group_1,
                            file=io_file(data={'A': 2}),
                            name=fn)
        manager.upload_file(group_id=group_2,
                            file=io_file(data={'A': 3}),
                            name=fn)
    # -- Test list files for groups -------------------------------------------
    with database.session() as session:
        manager = WorkflowGroupManager(session=session, fs=fs)
        files = manager.list_uploaded_files(group_id=group_1)
        assert len(files) == 2
        files = manager.list_uploaded_files(group_id=group_2)
        assert len(files) == 1
Пример #4
0
def test_delete_group(database, tmpdir):
    """Test creating and deleting workflow groups."""
    # -- Setup ----------------------------------------------------------------
    #
    # Create a database with two groups for a single workflow.
    fs = FileSystemStorage(basedir=tmpdir)
    with database.session() as session:
        user_id = model.create_user(session, active=True)
        wf_id = model.create_workflow(session)
        manager = WorkflowGroupManager(session=session, fs=fs)
        group_1 = manager.create_group(workflow_id=wf_id,
                                       name='A',
                                       user_id=user_id,
                                       parameters=ParameterIndex(),
                                       workflow_spec=dict()).group_id
        group_2 = manager.create_group(workflow_id=wf_id,
                                       name='B',
                                       user_id=user_id,
                                       parameters=ParameterIndex(),
                                       workflow_spec=dict()).group_id
    # -- Delete group ---------------------------------------------------------
    with database.session() as session:
        # Ensure that group directores are deleted.
        manager = WorkflowGroupManager(session=session, fs=fs)
        manager.delete_group(group_1)
        # Access to group 1 raises error while group 2 is still accessible.
        with pytest.raises(err.UnknownWorkflowGroupError):
            manager.get_group(group_1)
        assert manager.get_group(group_2) is not None
Пример #5
0
def test_upload_file(database, tmpdir):
    """Test uploading files."""
    # -- Setup ----------------------------------------------------------------
    #
    # Create a database with two groups for a single workflow. Upload one file
    # for each group.
    fs = FileSystemStorage(basedir=tmpdir)
    with database.session() as session:
        user_1 = model.create_user(session, active=True)
        workflow_id = model.create_workflow(session)
        group_1 = model.create_group(session, workflow_id, users=[user_1])
    # -- Test upload file -----------------------------------------------------
    data = {'A': 1}
    with database.session() as session:
        manager = WorkflowGroupManager(session=session, fs=fs)
        fh = manager.upload_file(group_id=group_1,
                                 file=io_file(data={'A': 1}),
                                 name='A.json')
        assert fh.name == 'A.json'
        assert fh.mime_type == 'application/json'
        fh = manager.get_uploaded_file(group_id=group_1, file_id=fh.file_id)
        assert json.load(fh.open()) == data
    # -- Test error case ------------------------------------------------------
    data = {'A': 1}
    with database.session() as session:
        with pytest.raises(err.ConstraintViolationError):
            manager.upload_file(group_id=group_1,
                                file=io_file(data={'A': 1}),
                                name=' ')
        with pytest.raises(err.UnknownWorkflowGroupError):
            manager.upload_file(group_id='UNKNOWN',
                                file=io_file(data={'A': 1}),
                                name=' ')
def init(database, basedir):
    """Create a fresh database with one user, two workflows, and four groups
    for each workflow. Each group has three active runs. Returns a a list of
    tuples with workflow_id, groups, and runs.
    """
    with database.session() as session:
        user_id = model.create_user(session, active=True)
        # Add two workflow templates.
        workflows = list()
        for i, schema in enumerate([SCHEMA_1, SCHEMA_2]):
            workflow_id = model.create_workflow(session, result_schema=schema)
            workflows.append(workflow_id)
        objects = list()
        for workflow_id in workflows:
            groups = list()
            for i in range(4):
                group_id = model.create_group(session,
                                              workflow_id,
                                              users=[user_id])
                runs = list()
                for j in range(3):
                    run_id = model.create_run(session, workflow_id, group_id)
                    runs.append(run_id)
                groups.append((group_id, runs))
            objects.append((workflow_id, groups))
        return objects
Пример #7
0
def test_delete_file(fscls, database, tmpdir):
    """Test deleting an uploaded file."""
    # -- Setup ----------------------------------------------------------------
    #
    # Create a database with two groups for a single workflow. Upload one file
    # for each group.
    file = io_file(data={'A': 1})
    fn = 'data.json'
    fs = fscls(env=Config().basedir(tmpdir))
    with database.session() as session:
        user_1 = model.create_user(session, active=True)
        workflow_id = model.create_workflow(session)
        group_1 = model.create_group(session, workflow_id, users=[user_1])
        group_2 = model.create_group(session, workflow_id, users=[user_1])
        manager = WorkflowGroupManager(session=session, fs=fs)
        fh = manager.upload_file(group_id=group_1, file=file, name=fn)
        file_1 = fh.file_id
        fh = manager.upload_file(group_id=group_2, file=file, name=fn)
        file_2 = fh.file_id
    # -- Test delete file -----------------------------------------------------
    with database.session() as session:
        manager = WorkflowGroupManager(session=session, fs=fs)
        fh = manager.get_uploaded_file(group_id=group_1, file_id=file_1)
        manager.delete_file(group_id=group_1, file_id=file_1)
        # File 1 can no longer be accessed while file 2 is still present.
        with pytest.raises(err.UnknownFileError):
            manager.get_uploaded_file(group_id=group_1, file_id=file_1).open()
        fh = manager.get_uploaded_file(group_id=group_2, file_id=file_2)
    # -- Error cases ----------------------------------------------------------
    with database.session() as session:
        # - Delete unknown file
        manager = WorkflowGroupManager(session=session, fs=fs)
        with pytest.raises(err.UnknownFileError):
            manager.delete_file(group_id=group_1, file_id=file_1)
Пример #8
0
def test_cancel_run(fscls, database, tmpdir):
    """Test setting run state to canceled."""
    # -- Setup ----------------------------------------------------------------
    fs = fscls(env=Config().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])
    # -- Test set run to error state ------------------------------------------
    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))
        run_id = run.run_id
        state = run.state()
        runs.update_run(run_id=run_id, state=state.cancel())
    with database.session() as session:
        runs = RunManager(session=session, fs=fs)
        run = runs.get_run(run_id)
        state = run.state()
        assert not state.is_active()
        assert not state.is_pending()
        assert not state.is_running()
        assert state.is_canceled()
        assert not state.is_error()
        assert not state.is_success()
        assert len(state.messages) == 1
Пример #9
0
def test_list_runs(fscls, database, tmpdir):
    """Test retrieving a list of run descriptors."""
    # -- Setup ----------------------------------------------------------------
    #
    # Create two runs: one in running state and one in error state.
    fs = fscls(env=Config().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])
        groups = WorkflowGroupManager(session=session, fs=fs)
        runs = RunManager(session=session, fs=fs)
        group = groups.get_group(group_id)
        # Run 1 in running state
        r = runs.create_run(group=group)
        run_1 = r.run_id
        runs.update_run(run_id=run_1, state=r.state().start())
        r = runs.create_run(group=group)
        run_2 = r.run_id
        runs.update_run(run_id=run_2, state=r.state().error())
    # -- Test get listing -----------------------------------------------------
    with database.session() as session:
        runs = RunManager(session=session, fs=fs)
        run_index = dict()
        for run in runs.list_runs(group_id):
            run_index[run.run_id] = run
        assert len(run_index) == 2
        assert run_index[run_1].state().is_running()
        assert run_index[run_2].state().is_error()
    # -- Test polling runs ----------------------------------------------------
    with database.session() as session:
        runs = RunManager(session=session, fs=fs)
        assert len(runs.list_runs(group_id)) == 2
        assert len(runs.list_runs(group_id, state=st.STATE_ERROR)) == 1
        assert len(runs.list_runs(group_id, state=st.STATE_SUCCESS)) == 0
Пример #10
0
def test_invalid_state_transitions(fscls, database, tmpdir):
    """Test error cases for invalid state transitions."""
    # -- Setup ----------------------------------------------------------------
    fs = fscls(env=Config().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])
    # -- Test set active run to pending ---------------------------------------
    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))
        run_id = run.run_id
        state = run.state()
        runs.update_run(run_id=run_id, state=state.start())
        with pytest.raises(err.ConstraintViolationError):
            runs.update_run(run_id=run_id, state=st.StatePending())
    # Cancel run
    with database.session() as session:
        runs = RunManager(session=session, fs=fs)
        runs.update_run(run_id=run_id, state=state.cancel())
    # -- Test cannot set run to any of the inactive states --------------------
    with database.session() as session:
        groups = WorkflowGroupManager(session=session, fs=fs)
        runs = RunManager(session=session, fs=fs)
        assert runs.update_run(run_id=run_id, state=state.cancel()) is None
        with pytest.raises(err.ConstraintViolationError):
            runs.update_run(run_id=run_id, state=state.error())
        with pytest.raises(err.ConstraintViolationError):
            runs.update_run(run_id=run_id, state=state.success())
Пример #11
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
Пример #12
0
def test_list_groups(database, tmpdir):
    """Test listing groups by user or by workflow."""
    # -- Setup ----------------------------------------------------------------
    #
    # Create a database with three groups for a two workflow. Group 1 has
    # user 1 as only member, group 2 has user 2 and 3 as member, group 3 has
    # user 1 and 3 as members.
    fs = FileSystemStorage(basedir=tmpdir)
    with database.session() as session:
        user_1 = model.create_user(session, active=True)
        user_2 = model.create_user(session, active=True)
        user_3 = model.create_user(session, active=True)
        workflow_1 = model.create_workflow(session)
        workflow_2 = model.create_workflow(session)
        members_1 = [user_1]
        group_1 = model.create_group(session, workflow_1, users=members_1)
        members_2 = [user_2, user_3]
        group_2 = model.create_group(session, workflow_1, users=members_2)
        members_3 = [user_1, user_3]
        group_3 = model.create_group(session, workflow_2, users=members_3)
    # -- Test list all groups -------------------------------------------------
    with database.session() as session:
        manager = WorkflowGroupManager(session=session, fs=fs)
        assert len(manager.list_groups()) == 3
        assert len(manager.list_groups(workflow_1)) == 2
        assert len(manager.list_groups(workflow_2)) == 1
    # -- Test list groups for users -------------------------------------------
    with database.session() as session:
        manager = WorkflowGroupManager(session=session, fs=fs)
        # User 1 is member of group 1 and 3.
        groups = manager.list_groups(user_id=user_1)
        assert len(groups) == 2
        assert [g.name for g in groups] == [group_1, group_3]
        # User 2 is member of group 2.
        groups = manager.list_groups(user_id=user_2)
        assert len(groups) == 1
        assert [g.name for g in groups] == [group_2]
        # User 3 is member of group 2 and 3.
        groups = manager.list_groups(user_id=user_3)
        assert len(groups) == 2
        assert [g.name for g in groups] == [group_2, group_3]
Пример #13
0
def test_group_handle_serialization(database, tmpdir):
    """Test serialization of workflow group handles."""
    config = Config().basedir(tmpdir)
    view = WorkflowGroupSerializer()
    with database.session() as session:
        manager = WorkflowGroupManager(session=session, fs=FileSystemStore(config))
        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])
        manager.upload_file(group_id=group_id, file=io_file(data={'A': 1}), name='a.json')
        group = manager.get_group(group_id)
        doc = view.group_handle(group)
        validator('UserGroupHandle').validate(doc)
        assert len(doc[labels.GROUP_MEMBERS]) == 1
def test_group_and_run_membership(database, authcls, open_access):
    """Test functionality for verifying that (a) a group or run exists, and
    (b) that a user is member of a group or run.
    """
    # -- Setup ----------------------------------------------------------------
    #
    # Create a database with two active users and one group and run where only
    # user 1 is a member of.
    with database.session() as session:
        user_1 = model.create_user(session, active=True)
        user_2 = model.create_user(session, active=True)
        workflow_id = model.create_workflow(session)
        group_id = model.create_group(session, workflow_id, users=[user_1])
        run_id = model.create_run(session, workflow_id, group_id)
    # -- Test group or run exists ---------------------------------------------
    with database.session() as session:
        auth = authcls(session)
        assert auth.group_or_run_exists(group_id=group_id) == group_id
        assert auth.group_or_run_exists(run_id=run_id) == group_id
        with pytest.raises(err.UnknownWorkflowGroupError):
            auth.group_or_run_exists(group_id=run_id)
        with pytest.raises(err.UnknownRunError):
            auth.group_or_run_exists(run_id=group_id)
    # -- Test group and run membership ----------------------------------------
    with database.session() as session:
        auth = authcls(session)
        assert auth.is_group_member(user_1, group_id=group_id)
        assert auth.is_group_member(user_1, run_id=run_id)
        assert auth.is_group_member(user_2, group_id=group_id) == open_access
        assert auth.is_group_member(user_2, run_id=run_id) == open_access
    # -- Error cases ----------------------------------------------------------
    with database.session() as session:
        auth = authcls(session)
        with pytest.raises(ValueError):
            auth.group_or_run_exists()
        with pytest.raises(ValueError):
            auth.group_or_run_exists(group_id=group_id, run_id=run_id)
Пример #15
0
def test_group_listing_serialization(database, tmpdir):
    """Test serialization of workflow group listing."""
    config = Config().basedir(tmpdir)
    view = WorkflowGroupSerializer()
    with database.session() as session:
        manager = WorkflowGroupManager(session=session, fs=FileSystemStore(config))
        user_id = model.create_user(session, active=True)
        workflow_id = model.create_workflow(session)
        model.create_group(session, workflow_id, users=[user_id])
        model.create_group(session, workflow_id, users=[user_id])
        groups = manager.list_groups(workflow_id=workflow_id, user_id=user_id)
        assert len(groups) == 2
        doc = view.group_listing(groups)
        validator('UserGroupListing').validate(doc)
        assert len(doc[labels.GROUP_LIST]) == 2
Пример #16
0
def test_login_after_timeout(database, authcls):
    """Test login after key expired."""
    # -- Setup ----------------------------------------------------------------
    #
    # Create a database with a single active user.
    with database.session() as session:
        user_1 = model.create_user(session, active=True)
    # Test login after timeout -----------------------------------------
    with database.session() as session:
        # Create user manager with TTL for login tokens of 1 sec.
        users = UserManager(session, token_timeout=1)
        # Authenticate user 1. Then sleep for 1.5 sec. When logging in again an
        # new api-key is generated.
        api_key = users.login_user(user_1, user_1).api_key.value
        time.sleep(1.5)
        assert users.login_user(user_1, user_1).api_key.value != api_key
Пример #17
0
def error_run(database, fs, messages):
    """Create a run that is in error state. Returns the identifier of the
    created workflow, group, and run.
    """
    # Setup temporary run folder.
    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])
        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=run_id, state=state)
        messages = ['There', 'were', 'many errors']
        runs.update_run(run_id=run_id, state=state.error(messages))
    return workflow_id, group_id, run_id
Пример #18
0
def test_authenticate_after_timeout(database, authcls):
    """Test authentication after key expired."""
    # -- Setup ----------------------------------------------------------------
    #
    # Create a database with a single active user.
    with database.session() as session:
        user_1 = model.create_user(session, active=True)
    # Test authenticate after timeout -----------------------------------------
    with database.session() as session:
        # Create user manager with TTL for login tokens of 1 sec.
        users = UserManager(session, token_timeout=1)
        auth = authcls(session)
        # Authenticate user 1. Then sleep for 1.5 sec. Trying to authenticate
        # the user after the sleep period should raise an error.
        api_key = users.login_user(user_1, user_1).api_key.value
        time.sleep(1.5)
        with pytest.raises(err.UnauthenticatedAccessError):
            auth.authenticate(api_key)
Пример #19
0
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
Пример #20
0
def test_file_listing_serialization(database, tmpdir):
    """Test serialization of file handles."""
    view = UploadFileSerializer()
    filename = 'data.json'
    with database.session() as session:
        manager = WorkflowGroupManager(session=session,
                                       fs=FileSystemStorage(basedir=tmpdir))
        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])
        fh = manager.upload_file(group_id=group_id,
                                 file=io_file(data={'A': 1}),
                                 name=filename)
        doc = view.file_handle(group_id=group_id, fh=fh)
        assert doc[labels.FILE_NAME] == filename
        validator('FileHandle').validate(doc)
        doc = view.file_listing(
            group_id=group_id,
            files=manager.list_uploaded_files(group_id=group_id))
        validator('FileListing').validate(doc)
Пример #21
0
def test_create_run_errors(fscls, database, tmpdir):
    """Test error cases for create_run parameter combinations."""
    # -- Setup ----------------------------------------------------------------
    fs = fscls(env=Config().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])
    # -- Test create_run with invalid arguments -------------------------------
    with database.session() as session:
        wfrepo = WorkflowManager(session=session, fs=fs)
        groups = WorkflowGroupManager(session=session, fs=fs)
        runs = RunManager(session=session, fs=fs)
        workflow = wfrepo.get_workflow(workflow_id)
        group = groups.get_group(group_id)
        with pytest.raises(ValueError):
            runs.create_run()
        with pytest.raises(ValueError):
            runs.create_run(workflow=workflow, group=group)
        with pytest.raises(ValueError):
            runs.create_run(group=group, runs=['A'])
Пример #22
0
def test_get_file(database, tmpdir):
    """Test accessing uploaded files."""
    # -- Setup ----------------------------------------------------------------
    #
    # Create a database with two groups for a single workflow. Upload one file
    # for each group.
    data_1 = {'A': 1}
    data_2 = {'B': 2}
    f1 = io_file(data=data_1)
    f2 = io_file(data=data_2)
    fn = 'data.json'
    fs = FileSystemStorage(basedir=tmpdir)
    with database.session() as session:
        user_1 = model.create_user(session, active=True)
        workflow_id = model.create_workflow(session)
        group_1 = model.create_group(session, workflow_id, users=[user_1])
        group_2 = model.create_group(session, workflow_id, users=[user_1])
        mngr = WorkflowGroupManager(session=session, fs=fs)
        file_1 = mngr.upload_file(group_id=group_1, file=f1, name=fn).file_id
        file_2 = mngr.upload_file(group_id=group_2, file=f2, name=fn).file_id
    files = [(group_1, file_1, data_1), (group_2, file_2, data_2)]
    # -- Test get file --------------------------------------------------------
    with database.session() as session:
        manager = WorkflowGroupManager(session=session, fs=fs)
        for g_id, f_id, data in files:
            fh = manager.get_uploaded_file(group_id=g_id, file_id=f_id)
            assert fh.name == fn
            assert fh.mime_type == 'application/json'
            assert json.load(fh.open()) == data
    # -- Test error cases -----------------------------------------------------
    # - File handle is unknown for s2
    with database.session() as session:
        manager = WorkflowGroupManager(session=session, fs=fs)
        with pytest.raises(err.UnknownFileError):
            manager.get_uploaded_file(group_id=group_2, file_id=file_1).open()
        # - Access file with unknown file identifier
        with pytest.raises(err.UnknownFileError):
            manager.get_uploaded_file(group_id=group_1, file_id='UNK').open()
Пример #23
0
def test_create_group(database, tmpdir):
    """Test creating and retrieving new workflow groups."""
    # -- Setup ----------------------------------------------------------------
    #
    # Create a database with a single workflow.
    fs = FileSystemStorage(basedir=tmpdir)
    with database.session() as session:
        user_id = model.create_user(session, active=True)
        workflow_id = model.create_workflow(session)
    # -- Test create group ----------------------------------------------------
    with database.session() as session:
        manager = WorkflowGroupManager(session=session, fs=fs)
        group = manager.create_group(workflow_id=workflow_id,
                                     name='Group 1',
                                     user_id=user_id,
                                     parameters=ParameterIndex(),
                                     workflow_spec=dict())
        assert group.name == 'Group 1'
        assert group.owner_id == user_id
        assert group.engine_config is None
        assert len(group.members) == 1
        assert isinstance(group.parameters, dict)
        assert len(group.parameters) == 0
        assert isinstance(group.workflow_spec, dict)
        assert len(group.workflow_spec) == 0
        # Retrieve the group from the database
        group = manager.get_group(group.group_id)
        assert group.name == 'Group 1'
        assert group.owner_id == user_id
        assert len(group.members) == 1
        assert isinstance(group.parameters, dict)
        assert len(group.parameters) == 0
        assert isinstance(group.workflow_spec, dict)
        assert len(group.workflow_spec) == 0
    # -- Test create group with duplicate members and different config --------
    engine_config = {'workers': {'test': {'worker': 'docker'}}}
    with database.session() as session:
        manager = WorkflowGroupManager(session=session, fs=fs)
        group = manager.create_group(workflow_id=workflow_id,
                                     name='Group 2',
                                     user_id=user_id,
                                     parameters=ParameterIndex(),
                                     workflow_spec=dict(),
                                     members=[user_id, user_id, user_id],
                                     engine_config=engine_config)
        assert len(group.members) == 1
        assert group.engine_config == engine_config
        # Retrieve the group from the database
        group = manager.get_group(group.group_id)
        assert len(group.members) == 1
    # -- Test error cases -----------------------------------------------------
    with database.session() as session:
        manager = WorkflowGroupManager(session=session, fs=fs)
        # - Invalid name
        with pytest.raises(err.ConstraintViolationError):
            manager.create_group(workflow_id=workflow_id,
                                 name='A' * 513,
                                 user_id=user_id,
                                 parameters=ParameterIndex(),
                                 workflow_spec=dict())
        # - Duplicate name
        with pytest.raises(err.ConstraintViolationError):
            manager.create_group(workflow_id=workflow_id,
                                 name='Group 1',
                                 user_id=user_id,
                                 parameters=ParameterIndex(),
                                 workflow_spec=dict())
        # - Unknown user
        with pytest.raises(err.UnknownUserError):
            manager.create_group(workflow_id=workflow_id,
                                 name='D',
                                 user_id=user_id,
                                 parameters=ParameterIndex(),
                                 workflow_spec=dict(),
                                 members=[user_id, 'not a user'])
        # - Missing user
        with pytest.raises(err.UnknownUserError):
            manager.create_group(workflow_id=workflow_id,
                                 name='D',
                                 user_id=None,
                                 parameters=ParameterIndex(),
                                 workflow_spec=dict(),
                                 members=[user_id, 'not a user'])
Пример #24
0
def test_authenticate_user(database, authcls):
    """Test user login and logout. Uses a database with two active and one
    inactive user to validate that active users can login and logout while
    inactive users cannot login.
    """
    # -- Setup ----------------------------------------------------------------
    #
    # Create a database with two active and one inactive users.
    with database.session() as session:
        user_1 = model.create_user(session, active=True)
        user_2 = model.create_user(session, active=True)
        user_3 = model.create_user(session, active=False)
    # -- Test login -----------------------------------------------------------
    with database.session() as session:
        users = UserManager(session)
        token_1 = users.login_user(user_1, user_1).api_key.value
        token_2 = users.login_user(user_2, user_2).api_key.value
    # -- Test authentication --------------------------------------------------
    with database.session() as session:
        auth = authcls(session)
        # Authentication of logged-in users using the API key should return the
        # respective user identifier.
        assert auth.authenticate(token_1).user_id == user_1
        assert auth.authenticate(token_2).user_id == user_2
    # -- Test logout ----------------------------------------------------------
    with database.session() as session:
        # Logout user 1. User 2 should still be able to authenticate while a
        # user that is logged out cannot.
        users = UserManager(session)
        auth = authcls(session)
        assert users.logout_user(token_1).user_id == user_1
        # Authenticating user 1 will raise exception.
        with pytest.raises(err.UnauthenticatedAccessError):
            auth.authenticate(token_1)
        # Logging out a user that is not logged in will not raise error>
        assert users.logout_user(token_1) is None
        # User 2 can still authenticate.
        assert auth.authenticate(token_2).user_id == user_2
    # -- Test re-login --------------------------------------------------------
    with database.session() as session:
        # Login user 1 again.
        users = UserManager(session)
        auth = authcls(session)
        token_1 = users.login_user(user_1, user_1).api_key.value
        # User 1 and 2 can now be authenticated again.
        assert auth.authenticate(token_1).user_id == user_1
        assert auth.authenticate(token_2).user_id == user_2
        # If a logged in user logs in the previous key does not become invalid.
        token_3 = users.login_user(user_1, user_1).api_key.value
        assert auth.authenticate(token_1).user_id == user_1
        assert auth.authenticate(token_3).user_id == user_1
    # -- Error cases ----------------------------------------------------------
    with database.session() as session:
        users = UserManager(session)
        auth = authcls(session)
        # Attempt to authenticate unknown user raises error
        with pytest.raises(err.UnknownUserError):
            users.login_user('unknown', user_1)
        # Attempt to authenticate with invalid password will raises error
        with pytest.raises(err.UnknownUserError):
            users.login_user(user_1, user_2)
        # Inactive user 3 should not be able to login.
        with pytest.raises(err.UnknownUserError):
            users.login_user(user_3, user_3)
        # An error is raised when using an invalid API key.
        with pytest.raises(err.UnauthenticatedAccessError):
            assert auth.authenticate('UNKNOWN')