예제 #1
0
def check_video_download(api_app, event_id, access_token, json_headers, data,
                         video_1_id, video_1_depid, users):
    """Try to delete downloaded files via REST API."""
    task_id = data['global_status'][0][0]['file_download']['id']
    with api_app.test_request_context():
        url = url_for('invenio_webhooks.task_item',
                      receiver_id='avc',
                      event_id=event_id,
                      task_id=task_id,
                      access_token=access_token)
    with api_app.test_client() as client, \
            mock.patch('invenio_sse.ext._SSEState.publish'), \
            mock.patch('invenio_indexer.api.RecordIndexer.bulk_index'):
        sse_channel = 'mychannel'
        payload = dict(sse_channel=sse_channel)
        resp = client.delete(url,
                             headers=json_headers,
                             data=json.dumps(payload))

        assert resp.status_code == 204

    # Create + Delete Download
    assert ObjectVersion.query.count() == (
        get_object_count() + get_object_count(frames=False, transcode=False))
    assert ObjectVersionTag.query.count() == get_tag_count()

    # check extracted metadata is not there
    record = RecordMetadata.query.get(video_1_id)
    assert 'extracted_metadata' in record.json['_cds']
예제 #2
0
def test_video_extract_frames(app, db, bucket, video):
    """Test extract frames from video."""
    obj = ObjectVersion.create(bucket=bucket,
                               key='video.mp4',
                               stream=open(video, 'rb'))
    add_video_tags(obj)
    version_id = str(obj.version_id)
    db.session.commit()
    assert ObjectVersion.query.count() == 1

    task_s = ExtractFramesTask().s(version_id=version_id)

    # Extract frames
    task_s.delay()
    assert ObjectVersion.query.count() == get_object_count(transcode=False)

    frames_and_gif = ObjectVersion.query.join(ObjectVersion.tags).filter(
        ObjectVersionTag.key == 'master',
        ObjectVersionTag.value == version_id).all()
    assert len(frames_and_gif) == get_object_count(download=False,
                                                   transcode=False)
    assert ObjectVersion.query.count() == 12

    # Undo
    ExtractFramesTask().clean(version_id=version_id)

    # master file + create frames + delete frames
    assert ObjectVersion.query.count() == 23  # master file
    frames_and_gif = ObjectVersion.query.join(ObjectVersion.tags).filter(
        ObjectVersionTag.key == 'master',
        ObjectVersionTag.value == version_id).all()
    assert len(frames_and_gif) == 11
예제 #3
0
def check_video_frames(api_app, event_id, access_token,
                       json_headers, data, video_1_id, video_1_depid, users):
    """Try to delete video frames via REST API."""
    task_id = data['global_status'][1][0]['file_video_extract_frames']['id']
    with api_app.test_request_context():
        url = url_for(
            'invenio_webhooks.task_item',
            receiver_id='avc',
            event_id=event_id,
            task_id=task_id,
            access_token=access_token
        )
    with api_app.test_client() as client, \
            mock.patch('invenio_indexer.tasks.index_record.delay'):
        resp = client.delete(url, headers=json_headers)

        assert resp.status_code == 204

    assert ObjectVersion.query.count() == (
        get_object_count() +
        get_object_count(download=False, transcode=False)
    )
    assert ObjectVersionTag.query.count() == get_tag_count()

    # check extracted metadata is there
    record = RecordMetadata.query.get(video_1_id)
    assert 'extracted_metadata' in record.json['_cds']
예제 #4
0
def test_avc_workflow_receiver_clean_extract_metadata(api_app, db, cds_depid,
                                                      access_token,
                                                      json_headers,
                                                      mock_sorenson,
                                                      online_video, webhooks):
    """Test AVCWorkflow receiver."""
    master_key = 'test.mp4'
    with api_app.test_request_context():
        url = url_for('invenio_webhooks.event_list',
                      receiver_id='avc',
                      access_token=access_token)

    with api_app.test_client() as client:
        sse_channel = 'mychannel'
        payload = dict(
            uri=online_video,
            deposit_id=cds_depid,
            key=master_key,
            sse_channel=sse_channel,
            sleep_time=0,
        )
        # [[ RUN ]]
        resp = client.post(url, headers=json_headers, data=json.dumps(payload))

        assert resp.status_code == 201

    assert ObjectVersion.query.count() == get_object_count()
    assert ObjectVersionTag.query.count() == get_tag_count()

    # [[ CLEAN VIDEO METADATA EXTRACTION ]]
    event = Event.query.first()
    event.receiver.clean_task(event=event,
                              task_name='file_video_metadata_extraction')

    # check extracted metadata is not there
    records = RecordMetadata.query.all()
    assert len(records) == 1
    assert 'extracted_metadata' not in records[0].json['_cds']

    assert ObjectVersion.query.count() == get_object_count()
    assert ObjectVersionTag.query.count() == get_tag_count()

    # [[ RUN again metadata extraction ]]
    event.receiver.run_task(
        event=event, task_name='file_video_metadata_extraction').apply()

    # Metadata Extraction doesn't create new objects
    assert ObjectVersion.query.count() == get_object_count()
    # neither new tags, but update the current
    assert ObjectVersionTag.query.count() == get_tag_count()

    # check extracted metadata is there
    records = RecordMetadata.query.all()
    assert len(records) == 1
    assert 'extracted_metadata' in records[0].json['_cds']
예제 #5
0
def test_avc_workflow_receiver_clean_video_frames(
        api_app, db, cds_depid, access_token, json_headers,
        mock_sorenson, online_video, webhooks):
    """Test AVCWorkflow receiver."""
    master_key = 'test.mp4'
    with api_app.test_request_context():
        url = url_for(
            'invenio_webhooks.event_list',
            receiver_id='avc',
            access_token=access_token
        )

    with api_app.test_client() as client:
        payload = dict(
            uri=online_video,
            deposit_id=cds_depid,
            key=master_key,
            sleep_time=0,
        )
        resp = client.post(url, headers=json_headers, data=json.dumps(payload))

        assert resp.status_code == 201

    assert ObjectVersion.query.count() == get_object_count()
    assert ObjectVersionTag.query.count() == get_tag_count()

    event = Event.query.first()
    # [[ CLEAN VIDEO EXTRACT FRAMES ]]
    event.receiver.clean_task(
        event=event, task_name='file_video_extract_frames')

    # check extracted metadata is not there
    records = RecordMetadata.query.all()
    assert len(records) == 1
    assert 'extracted_metadata' in records[0].json['_cds']

    # Create + Clean Frames
    assert ObjectVersion.query.count() == (
        get_object_count() + get_object_count(download=False, transcode=False)
    )
    assert ObjectVersionTag.query.count() == get_tag_count()

    # RUN again frame extraction
    event.receiver.run_task(
        event=event, task_name='file_video_extract_frames').apply()

    # Create + Clean Frames + Restart Frames
    assert ObjectVersion.query.count() == (
        get_object_count() +
        2 * get_object_count(download=False, transcode=False)
    )
    assert ObjectVersionTag.query.count() == (
        get_tag_count() +
        get_tag_count(download=False, metadata=False, transcode=False)
    )
예제 #6
0
def test_avc_workflow_receiver_clean_download(api_app, db, cds_depid,
                                              access_token, json_headers,
                                              mock_sorenson, online_video,
                                              webhooks):
    """Test AVCWorkflow receiver."""
    master_key = 'test.mp4'
    with api_app.test_request_context():
        url = url_for('invenio_webhooks.event_list',
                      receiver_id='avc',
                      access_token=access_token)

    with api_app.test_client() as client:
        sse_channel = 'mychannel'
        payload = dict(
            uri=online_video,
            deposit_id=cds_depid,
            key=master_key,
            sse_channel=sse_channel,
            sleep_time=0,
        )
        resp = client.post(url, headers=json_headers, data=json.dumps(payload))

        assert resp.status_code == 201

    assert ObjectVersionTag.query.count() == get_tag_count()
    event = Event.query.first()
    # [[ CLEAN DOWNLOAD ]]
    event.receiver.clean_task(event=event, task_name='file_download')

    # check extracted metadata is there
    records = RecordMetadata.query.all()
    assert len(records) == 1
    assert 'extracted_metadata' in records[0].json['_cds']

    # Create + Clean 1 Download File
    assert ObjectVersion.query.count() == get_object_count() + 1
    assert ObjectVersionTag.query.count() == get_tag_count()

    # RUN again first step
    event.receiver._init_object_version(event=event)
    event.receiver._first_step(event=event).apply()

    # Create + Clean 1 Download File + Run First Step
    assert ObjectVersion.query.count() == get_object_count() + 2
    assert ObjectVersionTag.query.count() == (
        get_tag_count() + get_tag_count(frames=False, transcode=False))
예제 #7
0
def check_video_transcode_restart(api_app, event_id, access_token,
                                  json_headers, data, video_1_id,
                                  video_1_depid, users):
    """Try to delete transcoded file via REST API."""
    task_ids = [
        d['file_transcode']['id'] for d in data['global_status'][1]
        if 'file_transcode' in d and d['file_transcode']['status'] == 'SUCCESS'
    ]
    # RESTART FIRST TRANSCODED FILE
    with api_app.test_request_context():
        url = url_for('invenio_webhooks.task_item',
                      receiver_id='avc',
                      event_id=event_id,
                      task_id=task_ids[0],
                      access_token=access_token)
    with api_app.test_client() as client, \
            mock.patch('invenio_sse.ext._SSEState.publish') as mock_sse, \
            mock.patch('invenio_indexer.api.RecordIndexer.bulk_index'):
        sse_channel = 'mychannel'
        payload = dict(sse_channel=sse_channel)
        resp = client.put(url, headers=json_headers, data=json.dumps(payload))

        assert resp.status_code == 204

        assert mock_sse.called is True

    # Create + restart transcode (clean + create)
    assert ObjectVersion.query.count() == get_object_count() + 2
    # if changed, copy magic number 14 from helpers::get_tag_count
    assert ObjectVersionTag.query.count() == get_tag_count() + 14

    # check extracted metadata is there
    record = RecordMetadata.query.get(video_1_id)
    assert 'extracted_metadata' in record.json['_cds']

    # check task id is changed
    event = Event.query.first()
    new_task_id = event.response['global_status'][1][1]['file_transcode']['id']
    assert task_ids[0] != new_task_id
    old_result = AsyncResult(task_ids[0])
    new_result = AsyncResult(new_task_id)
    for key in ['tags', 'key', 'deposit_id', 'event_id', 'preset_quality']:
        assert old_result.result['payload'][key] == new_result.result[
            'payload'][key]
예제 #8
0
def test_avc_workflow_delete(api_app, db, api_project, users, access_token,
                             json_headers, mock_sorenson, online_video,
                             webhooks, checker):
    """Test AVCWorkflow receiver REST API."""
    project, video_1, video_2 = api_project
    video_1_id = video_1.id
    video_1_depid = video_1['_deposit']['id']
    master_key = 'test.mp4'

    with api_app.test_request_context():
        url = url_for('invenio_webhooks.event_list',
                      receiver_id='avc',
                      access_token=access_token)

    with api_app.test_client() as client, \
            mock.patch('invenio_sse.ext._SSEState.publish'), \
            mock.patch('invenio_indexer.api.RecordIndexer.bulk_index'):
        sse_channel = 'mychannel'
        payload = dict(
            uri=online_video,
            deposit_id=video_1_depid,
            key=master_key,
            sse_channel=sse_channel,
            sleep_time=0,
        )
        resp = client.post(url, headers=json_headers, data=json.dumps(payload))

        assert resp.status_code == 201
        data = json.loads(resp.data.decode('utf-8'))

    # check extracted metadata is there
    record = RecordMetadata.query.get(video_1_id)
    assert 'extracted_metadata' in record.json['_cds']

    assert ObjectVersion.query.count() == get_object_count()
    assert ObjectVersionTag.query.count() == get_tag_count()

    event_id = data['tags']['_event_id']
    video_1_id = str(deposit_video_resolver(video_1_depid).id)
    ###
    checker(api_app, event_id, access_token, json_headers, data, video_1_id,
            video_1_depid, users)
예제 #9
0
def test_avc_workflow_receiver_clean_video_transcode(api_app, db, cds_depid,
                                                     access_token,
                                                     json_headers,
                                                     mock_sorenson,
                                                     online_video, webhooks):
    """Test AVCWorkflow receiver."""
    master_key = 'test.mp4'
    with api_app.test_request_context():
        url = url_for('invenio_webhooks.event_list',
                      receiver_id='avc',
                      access_token=access_token)

    with api_app.test_client() as client:
        sse_channel = 'mychannel'
        payload = dict(
            uri=online_video,
            deposit_id=cds_depid,
            key=master_key,
            sse_channel=sse_channel,
            sleep_time=0,
        )
        resp = client.post(url, headers=json_headers, data=json.dumps(payload))

        assert resp.status_code == 201

    assert ObjectVersion.query.count() == get_object_count()
    assert ObjectVersionTag.query.count() == get_tag_count()

    #
    # CLEAN
    #
    presets = [p for p in get_presets_applied() if p != '1024p']
    for i, preset_quality in enumerate(presets, 1):
        # Clean transcode task for each preset
        event = Event.query.first()
        event.receiver.clean_task(event=event,
                                  task_name='file_transcode',
                                  preset_quality=preset_quality)

        # check extracted metadata is there
        records = RecordMetadata.query.all()
        assert len(records) == 1
        assert 'extracted_metadata' in records[0].json['_cds']

        # Create + Delete i-th transcoded files
        assert ObjectVersion.query.count() == get_object_count() + i
        assert ObjectVersionTag.query.count() == get_tag_count()

    # Create + Delete transcoded files
    assert ObjectVersion.query.count() == get_object_count() + len(presets)
    assert ObjectVersionTag.query.count() == get_tag_count()

    #
    # RUN again
    #
    for i, preset_quality in enumerate(presets, 1):
        event = Event.query.first()
        event.receiver.run_task(event=event,
                                task_name='file_transcode',
                                preset_quality=preset_quality).apply()

        # Create + Delete transcoded files + Restart i-th transcode
        assert ObjectVersion.query.count() == (get_object_count() +
                                               len(presets) + i)
        assert ObjectVersionTag.query.count() == get_tag_count() + (i * 13)
예제 #10
0
def test_avc_workflow_receiver_local_file_pass(api_app, db, api_project,
                                               access_token, json_headers,
                                               mock_sorenson, online_video,
                                               webhooks, local_file):
    """Test AVCWorkflow receiver."""
    project, video_1, video_2 = api_project
    video_1_depid = video_1['_deposit']['id']
    video_1_id = str(video_1.id)
    project_id = str(project.id)

    bucket_id = ObjectVersion.query.filter_by(
        version_id=local_file).one().bucket_id
    video_size = 5510872
    master_key = 'test.mp4'
    slave_keys = [
        'slave_{0}.mp4'.format(quality)
        for quality in get_presets_applied().keys() if quality != '1024p'
    ]
    with api_app.test_request_context():
        url = url_for('invenio_webhooks.event_list',
                      receiver_id='avc',
                      access_token=access_token)

    with api_app.test_client() as client, \
            mock.patch('invenio_sse.ext._SSEState.publish') as mock_sse, \
            mock.patch('invenio_indexer.api.RecordIndexer.bulk_index') \
            as mock_indexer:
        sse_channel = 'mychannel'
        payload = dict(
            uri=online_video,
            deposit_id=video_1_depid,
            key=master_key,
            sse_channel=sse_channel,
            sleep_time=0,
            version_id=str(local_file),
        )
        # [[ RUN WORKFLOW ]]
        resp = client.post(url, headers=json_headers, data=json.dumps(payload))

        assert resp.status_code == 201
        data = json.loads(resp.data.decode('utf-8'))

        assert '_tasks' in data
        assert data['key'] == master_key
        assert 'version_id' in data
        assert data.get('presets') == get_available_preset_qualities()
        assert 'links' in data  # TODO decide with links are needed

        assert ObjectVersion.query.count() == get_object_count()

        # Master file
        master = ObjectVersion.get(bucket_id, master_key)
        tags = master.get_tags()
        assert tags['_event_id'] == data['tags']['_event_id']
        assert master.key == master_key
        assert str(master.version_id) == data['version_id']
        assert master.file
        assert master.file.size == video_size

        # Check metadata tags
        metadata_keys = [
            'duration', 'bit_rate', 'size', 'avg_frame_rate', 'codec_name',
            'codec_long_name', 'width', 'height', 'nb_frames',
            'display_aspect_ratio', 'color_range'
        ]
        assert all([key in tags for key in metadata_keys])
        assert ObjectVersion.query.count() == get_object_count()
        assert ObjectVersionTag.query.count() == get_tag_count(is_local=True)

        # Check metadata patch
        recid = PersistentIdentifier.get('depid', video_1_depid).object_uuid
        record = Record.get_record(recid)
        assert 'extracted_metadata' in record['_cds']
        assert all([
            key in str(record['_cds']['extracted_metadata'])
            for key in metadata_keys
        ])

        # Check slaves
        for slave_key in slave_keys:
            slave = ObjectVersion.get(bucket_id, slave_key)
            tags = slave.get_tags()
            assert slave.key == slave_key
            assert '_sorenson_job_id' in tags
            assert tags['_sorenson_job_id'] == '1234'
            assert 'master' in tags
            assert tags['master'] == str(master.version_id)
            assert master.file
            assert master.file.size == video_size

        video = deposit_video_resolver(video_1_depid)
        events = get_deposit_events(video['_deposit']['id'])

        # check deposit tasks status
        tasks_status = get_tasks_status_by_task(events)
        assert len(tasks_status) == 3
        assert 'file_transcode' in tasks_status
        assert 'file_video_extract_frames' in tasks_status
        assert 'file_video_metadata_extraction' in tasks_status

        # check single status
        collector = CollectInfoTasks()
        iterate_events_results(events=events, fun=collector)
        info = list(collector)
        assert len(info) == 11
        assert info[0][0] == 'file_video_metadata_extraction'
        assert info[0][1].status == states.SUCCESS
        assert info[1][0] == 'file_video_extract_frames'
        assert info[1][1].status == states.SUCCESS
        transocode_tasks = info[2:]
        statuses = [task[1].status for task in info[2:]]
        assert len(transocode_tasks) == len(statuses)
        assert [
            states.SUCCESS, states.REVOKED, states.REVOKED, states.REVOKED,
            states.SUCCESS, states.REVOKED, states.REVOKED, states.REVOKED,
            states.REVOKED
        ] == statuses

        # check tags (exclude 'uri-origin')
        assert ObjectVersionTag.query.count() == (get_tag_count() - 1)

        # check sse is called
        assert mock_sse.called

        messages = [
            (sse_channel, states.SUCCESS, 'file_video_metadata_extraction'),
            (sse_channel, states.STARTED, 'file_transcode'),
            (sse_channel, states.SUCCESS, 'file_transcode'),
            (sse_channel, states.REVOKED, 'file_transcode'),  # ResolutionError
            (sse_channel, states.STARTED, 'file_video_extract_frames'),
            (sse_channel, states.SUCCESS, 'file_video_extract_frames'),
            (sse_channel, states.SUCCESS, 'update_deposit'),
        ]

        call_args = []
        for (_, kwargs) in mock_sse.call_args_list:
            type_ = kwargs['type_']
            state = kwargs['data']['state']
            channel = kwargs['channel']
            tuple_ = (channel, state, type_)
            if tuple_ not in call_args:
                call_args.append(tuple_)

        assert len(call_args) == len(messages)
        for message in messages:
            assert message in call_args

        deposit = deposit_video_resolver(video_1_depid)

        def filter_events(call_args):
            _, x = call_args
            return x['type_'] == 'update_deposit'

        list_kwargs = list(filter(filter_events, mock_sse.call_args_list))
        assert len(list_kwargs) == 10
        _, kwargs = list_kwargs[8]
        assert kwargs['type_'] == 'update_deposit'
        assert kwargs['channel'] == 'mychannel'
        assert kwargs['data']['state'] == states.SUCCESS
        assert kwargs['data']['meta']['payload'] == {
            'deposit_id': deposit['_deposit']['id'],
            'event_id': data['tags']['_event_id'],
            'deposit': deposit,
        }

        # check ElasticSearch is called
        ids = set(get_indexed_records_from_mock(mock_indexer))
        assert video_1_id in ids
        assert project_id in ids
        assert deposit['_cds']['state'] == {
            'file_video_metadata_extraction': states.SUCCESS,
            'file_video_extract_frames': states.SUCCESS,
            'file_transcode': states.SUCCESS,
        }

    # Test cleaning!
    url = '{0}?access_token={1}'.format(data['links']['cancel'], access_token)

    with mock.patch('invenio_sse.ext._SSEState.publish') as mock_sse, \
            mock.patch('invenio_indexer.api.RecordIndexer.bulk_index') \
            as mock_indexer, \
            api_app.test_client() as client:
        # [[ DELETE WORKFLOW ]]
        resp = client.delete(url, headers=json_headers)

        assert resp.status_code == 201

        # check that object versions and tags are deleted
        # (Create + Delete) * Num Objs - 1 (because the file is local and will
        # be not touched)
        assert ObjectVersion.query.count() == 2 * get_object_count() - 1
        # Tags associated with the old version
        assert ObjectVersionTag.query.count() == get_tag_count(is_local=True)
        bucket = Bucket.query.first()
        # and bucket is empty
        assert bucket.size == 0

        record = RecordMetadata.query.filter_by(id=video_1_id).one()

        # check metadata patch are deleted
        assert 'extracted_metadata' not in record.json['_cds']

        # check the corresponding Event persisted after cleaning
        assert len(get_deposit_events(record.json['_deposit']['id'])) == 0
        assert len(
            get_deposit_events(record.json['_deposit']['id'],
                               _deleted=True)) == 1

        # check no SSE message and reindexing is fired
        assert mock_sse.called is False
        assert mock_indexer.called is False
예제 #11
0
def test_avc_workflow_receiver_pass(api_app, db, api_project, access_token,
                                    json_headers, mock_sorenson, online_video,
                                    webhooks, users):
    """Test AVCWorkflow receiver."""
    project, video_1, video_2 = api_project
    video_1_depid = video_1['_deposit']['id']
    video_1_id = str(video_1.id)
    project_id = str(project.id)

    bucket_id = video_1['_buckets']['deposit']
    video_size = 5510872
    master_key = 'test.mp4'
    slave_keys = [
        'slave_{0}.mp4'.format(quality) for quality in get_presets_applied()
        if quality != '1024p'
    ]
    with api_app.test_request_context():
        url = url_for('invenio_webhooks.event_list',
                      receiver_id='avc',
                      access_token=access_token)

    with api_app.test_client() as client, \
            mock.patch('invenio_sse.ext._SSEState.publish') as mock_sse, \
            mock.patch('invenio_indexer.api.RecordIndexer.bulk_index') \
            as mock_indexer:
        sse_channel = 'mychannel'
        payload = dict(
            uri=online_video,
            deposit_id=video_1_depid,
            key=master_key,
            sse_channel=sse_channel,
            sleep_time=0,
        )
        resp = client.post(url, headers=json_headers, data=json.dumps(payload))

        assert resp.status_code == 201
        data = json.loads(resp.data.decode('utf-8'))

        assert '_tasks' in data
        assert data['tags']['uri_origin'] == online_video
        assert data['key'] == master_key
        assert 'version_id' in data
        assert data.get('presets') == get_available_preset_qualities()
        assert 'links' in data  # TODO decide with links are needed

        assert ObjectVersion.query.count() == get_object_count()

        # Master file
        master = ObjectVersion.get(bucket_id, master_key)
        tags = master.get_tags()
        assert tags['_event_id'] == data['tags']['_event_id']
        assert master.key == master_key
        assert str(master.version_id) == data['version_id']
        assert master.file
        assert master.file.size == video_size

        # Check metadata tags
        metadata_keys = [
            'duration', 'bit_rate', 'size', 'avg_frame_rate', 'codec_name',
            'codec_long_name', 'width', 'height', 'nb_frames',
            'display_aspect_ratio', 'color_range'
        ]
        assert all([key in tags for key in metadata_keys])

        # Check metadata patch
        recid = PersistentIdentifier.get('depid', video_1_depid).object_uuid
        record = Record.get_record(recid)
        assert 'extracted_metadata' in record['_cds']
        assert all([
            key in str(record['_cds']['extracted_metadata'])
            for key in metadata_keys
        ])

        # Check slaves
        for slave_key in slave_keys:
            slave = ObjectVersion.get(bucket_id, slave_key)
            tags = slave.get_tags()
            assert slave.key == slave_key
            assert '_sorenson_job_id' in tags
            assert tags['_sorenson_job_id'] == '1234'
            assert 'master' in tags
            assert tags['master'] == str(master.version_id)
            assert master.file
            assert master.file.size == video_size

        video = deposit_video_resolver(video_1_depid)
        events = get_deposit_events(video['_deposit']['id'])

        # check deposit tasks status
        tasks_status = get_tasks_status_by_task(events)
        assert len(tasks_status) == 4
        assert 'file_download' in tasks_status
        assert 'file_transcode' in tasks_status
        assert 'file_video_extract_frames' in tasks_status
        assert 'file_video_metadata_extraction' in tasks_status

        # check single status
        collector = CollectInfoTasks()
        iterate_events_results(events=events, fun=collector)
        info = list(collector)
        presets = get_presets_applied().keys()
        assert info[0][0] == 'file_download'
        assert info[0][1].status == states.SUCCESS
        assert info[1][0] == 'file_video_metadata_extraction'
        assert info[1][1].status == states.SUCCESS
        assert info[2][0] == 'file_video_extract_frames'
        assert info[2][1].status == states.SUCCESS
        for i in info[3:]:
            assert i[0] == 'file_transcode'
            if i[1].status == states.SUCCESS:
                assert i[1].result['payload']['preset_quality'] in presets

        # check tags
        assert ObjectVersionTag.query.count() == get_tag_count()

        # check sse is called
        assert mock_sse.called

        messages = [
            (sse_channel, states.STARTED, 'file_download'),
            (sse_channel, states.SUCCESS, 'file_download'),
            (sse_channel, states.SUCCESS, 'file_video_metadata_extraction'),
            (sse_channel, states.STARTED, 'file_transcode'),
            (sse_channel, states.SUCCESS, 'file_transcode'),
            (sse_channel, states.REVOKED, 'file_transcode'),  # ResolutionError
            (sse_channel, states.STARTED, 'file_video_extract_frames'),
            (sse_channel, states.SUCCESS, 'file_video_extract_frames'),
            (sse_channel, states.SUCCESS, 'update_deposit'),
        ]

        call_args = []
        for (_, kwargs) in mock_sse.call_args_list:
            type_ = kwargs['type_']
            state = kwargs['data']['state']
            channel = kwargs['channel']
            tuple_ = (channel, state, type_)
            if tuple_ not in call_args:
                call_args.append(tuple_)

        assert len(call_args) == len(messages)
        for message in messages:
            assert message in call_args

        deposit = deposit_video_resolver(video_1_depid)

        def filter_events(call_args):
            _, x = call_args
            return x['type_'] == 'update_deposit'

        list_kwargs = list(filter(filter_events, mock_sse.call_args_list))
        assert len(list_kwargs) == 12
        _, kwargs = list_kwargs[10]
        assert kwargs['type_'] == 'update_deposit'
        assert kwargs['channel'] == 'mychannel'
        assert kwargs['data']['state'] == states.SUCCESS
        assert kwargs['data']['meta']['payload'] == {
            'deposit_id': deposit['_deposit']['id'],
            'event_id': data['tags']['_event_id'],
            'deposit': deposit,
        }

        # check ElasticSearch is called
        ids = set(get_indexed_records_from_mock(mock_indexer))
        assert video_1_id in ids
        assert project_id in ids
        assert deposit['_cds']['state'] == {
            'file_download': states.SUCCESS,
            'file_video_metadata_extraction': states.SUCCESS,
            'file_video_extract_frames': states.SUCCESS,
            'file_transcode': states.SUCCESS,
        }

    # check feedback from anoymous user
    event_id = data['tags']['_event_id']
    with api_app.test_request_context():
        url = url_for('invenio_webhooks.event_feedback_item',
                      event_id=event_id,
                      receiver_id='avc')
    with api_app.test_client() as client:
        resp = client.get(url, headers=json_headers)
        assert resp.status_code == 401
    # check feedback from owner
    with api_app.test_request_context():
        url = url_for('invenio_webhooks.event_feedback_item',
                      event_id=event_id,
                      receiver_id='avc')
    with api_app.test_client() as client:
        login_user_via_session(client, email=User.query.get(users[0]).email)
        resp = client.get(url, headers=json_headers)
        assert resp.status_code == 200
    # check feedback from another user without access
    with api_app.test_request_context():
        url = url_for('invenio_webhooks.event_feedback_item',
                      event_id=event_id,
                      receiver_id='avc')
    with api_app.test_client() as client:
        login_user_via_session(client, email=User.query.get(users[1]).email)
        resp = client.get(url, headers=json_headers)
        assert resp.status_code == 403
    # check feedback from another user with access
    user_2 = User.query.get(users[1])
    user_2_id = str(user_2.id)
    user_2_email = user_2.email
    project = deposit_project_resolver(project['_deposit']['id'])
    project['_access'] = {'update': [user_2_email]}
    project = project.commit()
    with api_app.test_request_context():
        url = url_for('invenio_webhooks.event_feedback_item',
                      event_id=event_id,
                      receiver_id='avc')
    with api_app.test_client() as client:

        @identity_loaded.connect
        def load_email(sender, identity):
            if current_user.get_id() == user_2_id:
                identity.provides.update([UserNeed(user_2_email)])

        login_user_via_session(client, email=user_2_email)
        resp = client.get(url, headers=json_headers)
        assert resp.status_code == 200

    # Test cleaning!
    url = '{0}?access_token={1}'.format(data['links']['cancel'], access_token)

    with mock.patch('invenio_sse.ext._SSEState.publish') as mock_sse, \
            mock.patch('invenio_indexer.api.RecordIndexer.bulk_index') \
            as mock_indexer, \
            api_app.test_client() as client:
        resp = client.delete(url, headers=json_headers)

        assert resp.status_code == 201

        # check that object versions and tags are deleted
        # (Create + Delete) * Num Objs
        assert ObjectVersion.query.count() == 2 * get_object_count()
        # Tags connected with the old version
        assert ObjectVersionTag.query.count() == get_tag_count()
        bucket = Bucket.query.first()
        # and bucket is empty
        assert bucket.size == 0

        record = RecordMetadata.query.filter_by(id=video_1_id).one()

        # check metadata patch are deleted
        assert 'extracted_metadata' not in record.json['_cds']

        # check the corresponding Event persisted after cleaning
        assert len(get_deposit_events(record.json['_deposit']['id'])) == 0
        assert len(
            get_deposit_events(record.json['_deposit']['id'],
                               _deleted=True)) == 1

        # check no SSE message and reindexing is fired
        assert mock_sse.called is False
        assert mock_indexer.called is False
예제 #12
0
def check_restart_avc_workflow(api_app, event_id, access_token, json_headers,
                               data, video_1_id, video_1_depid, users):
    """Try to restart AVC workflow via REST API."""
    with api_app.test_request_context():
        url = url_for('invenio_webhooks.event_item',
                      receiver_id='avc',
                      event_id=event_id,
                      access_token=access_token)
    with api_app.test_client() as client, \
            mock.patch('invenio_sse.ext._SSEState.publish') as mock_sse, \
            mock.patch('invenio_indexer.api.RecordIndexer.bulk_index') \
            as mock_indexer:
        sse_channel = 'mychannel'
        payload = dict(sse_channel=sse_channel)
        resp = client.put(url, headers=json_headers, data=json.dumps(payload))

        assert resp.status_code == 201

    # (Create + Clean + Create) * Objects Count
    assert ObjectVersion.query.count() == 3 * get_object_count()
    # (Version 1 + Version 2) * Tags Count
    assert ObjectVersionTag.query.count() == 2 * get_tag_count()

    # check extracted metadata is there
    record = RecordMetadata.query.get(video_1_id)
    assert 'extracted_metadata' in record.json['_cds']

    # check SSE
    assert mock_sse.called is True

    # check elasticsearch
    assert mock_indexer.called is True
    ids = get_indexed_records_from_mock(mock_indexer)
    setids = set(ids)
    assert len(setids) == 2
    assert video_1_id in setids

    # check restart from anonymous user
    with api_app.test_request_context():
        url = url_for(
            'invenio_webhooks.event_item',
            receiver_id='avc',
            event_id=event_id,
        )
    with api_app.test_client() as client:
        sse_channel = 'mychannel'
        payload = dict(sse_channel=sse_channel)
        resp = client.put(url, headers=json_headers, data=json.dumps(payload))
        assert resp.status_code == 401

    # check feedback from another user without access
    user_2 = User.query.get(users[1])
    user_2_email = user_2.email
    with api_app.test_request_context():
        url = url_for(
            'invenio_webhooks.event_item',
            receiver_id='avc',
            event_id=event_id,
        )
    with api_app.test_client() as client:
        sse_channel = 'mychannel'
        payload = dict(sse_channel=sse_channel)
        login_user_via_session(client, email=user_2_email)
        resp = client.put(url, headers=json_headers, data=json.dumps(payload))
        assert resp.status_code == 403

    # check feedback from another user with access
    user_2 = User.query.get(users[1])
    user_2_id = str(user_2.id)
    user_2_email = user_2.email
    project = deposit_video_resolver(video_1_depid).project
    project['_access'] = {'update': [user_2_email]}
    project.commit()
    with api_app.test_request_context():
        url = url_for(
            'invenio_webhooks.event_item',
            receiver_id='avc',
            event_id=event_id,
        )
    with api_app.test_client() as client:

        @identity_loaded.connect
        def load_email(sender, identity):
            if current_user.get_id() == user_2_id:
                identity.provides.update([UserNeed(user_2_email)])

        sse_channel = 'mychannel'
        payload = dict(sse_channel=sse_channel)
        login_user_via_session(client, email=user_2_email)
        resp = client.put(url, headers=json_headers, data=json.dumps(payload))
        assert resp.status_code == 201
예제 #13
0
def check_video_transcode_delete(api_app, event_id, access_token, json_headers,
                                 data, video_1_id, video_1_depid, users):
    """Try to delete transcoded file via REST API."""
    # get the list of task id of successfully transcode tasks
    task_ids = [
        d['file_transcode']['id'] for d in data['global_status'][1]
        if 'file_transcode' in d and d['file_transcode']['status'] == 'SUCCESS'
    ]
    # DELETE FIRST TRANSCODED FILE
    with api_app.test_request_context():
        url = url_for('invenio_webhooks.task_item',
                      receiver_id='avc',
                      event_id=event_id,
                      task_id=task_ids[0],
                      access_token=access_token)
    with api_app.test_client() as client, \
            mock.patch('invenio_sse.ext._SSEState.publish'), \
            mock.patch('invenio_indexer.api.RecordIndexer.bulk_index'):
        sse_channel = 'mychannel'
        payload = dict(sse_channel=sse_channel)
        resp = client.delete(url,
                             headers=json_headers,
                             data=json.dumps(payload))

        assert resp.status_code == 204

    # Create + Delete first transcode
    assert ObjectVersion.query.count() == (get_object_count() + 1)
    # Also if the tags are deleted, they remain associated with last version
    # of transcoded file
    assert ObjectVersionTag.query.count() == get_tag_count()

    # check extracted metadata is there
    record = RecordMetadata.query.get(video_1_id)
    assert 'extracted_metadata' in record.json['_cds']

    # check bucket size
    bucket = Bucket.query.first()
    assert bucket.size == 0

    # DELETE SECOND TRANSCODED FILE
    with api_app.test_request_context():
        url = url_for('invenio_webhooks.task_item',
                      receiver_id='avc',
                      event_id=event_id,
                      task_id=task_ids[1],
                      access_token=access_token)
    with api_app.test_client() as client, \
            mock.patch('invenio_sse.ext._SSEState.publish'), \
            mock.patch('invenio_indexer.api.RecordIndexer.bulk_index'):
        sse_channel = 'mychannel'
        payload = dict(sse_channel=sse_channel)
        resp = client.delete(url,
                             headers=json_headers,
                             data=json.dumps(payload))

        assert resp.status_code == 204

    # Create + 2 Deleted transcode files
    assert ObjectVersion.query.count() == get_object_count() + 2
    assert ObjectVersionTag.query.count() == get_tag_count()

    # check extracted metadata is there
    record = RecordMetadata.query.get(video_1_id)
    assert 'extracted_metadata' in record.json['_cds']