Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions api/jobs/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ def suggest(self, _id, cont_name, cid):
return suggest_container(gear, cont_name+'s', cid)

# Temporary Function
def upload(self):
def upload(self): # pragma: no cover
"""Upload new gear tarball file"""
if not self.user_is_admin:
self.abort(403, 'Request requires admin')
Expand All @@ -88,7 +88,7 @@ def upload(self):
return {'_id': str(gear_id)}

# Temporary Function
def download(self, **kwargs):
def download(self, **kwargs): # pragma: no cover
"""Download gear tarball file"""
dl_id = kwargs.pop('cid')
gear = get_gear(dl_id)
Expand Down Expand Up @@ -224,7 +224,7 @@ def delete(self, cid, rid):

class JobsHandler(base.RequestHandler):
"""Provide /jobs API routes."""
def get(self):
def get(self): # pragma: no cover (no route)
"""List all jobs."""
if not self.superuser_request and not self.user_is_admin:
self.abort(403, 'Request requires admin')
Expand Down
4 changes: 2 additions & 2 deletions api/placer.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,8 +250,8 @@ def check(self):

###
# Remove when switch to dmv2 is complete across all gears
c_metadata = self.metadata.get(self.container_type, {})
if self.context.get('job_id') and c_metadata and not c_metadata.get('files', []):
c_metadata = self.metadata.get(self.container_type, {}) # pragma: no cover
if self.context.get('job_id') and c_metadata and not c_metadata.get('files', []): # pragma: no cover
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately we are still waiting on the classifier update I believe, as it was updated to use the classification tag.

job = Job.get(self.context.get('job_id'))
input_names = [{'name': v.name} for v in job.inputs.itervalues()]

Expand Down
6 changes: 3 additions & 3 deletions api/resolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ class Node(object):

@staticmethod
def get_children(parent):
raise NotImplementedError()
raise NotImplementedError() # pragma: no cover

@staticmethod
def filter(children, criterion):
raise NotImplementedError()
raise NotImplementedError() # pragma: no cover

def _get_files(table, match):
"""
Expand Down Expand Up @@ -81,7 +81,7 @@ def filter(children, criterion):
for x in children:
if x['node_type'] == "file" and x.get('name') == criterion:
return x, FileNode
raise Exception('No ' + criterion + ' acquisition or file found.')
raise Exception('No ' + criterion + ' file found.')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice find.


class SessionNode(Node):

Expand Down
2 changes: 1 addition & 1 deletion api/web/start.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
# Enable code coverage for testing when API is started
# Start coverage before local module loading so their def and imports are counted
# http://coverage.readthedocs.io/en/coverage-4.2/faq.html
if os.environ.get("SCITRAN_RUNTIME_COVERAGE") == "true":
if os.environ.get("SCITRAN_RUNTIME_COVERAGE") == "true": # pragma: no cover - oh, the irony
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😂😂😂😂

def save_coverage(cov):
print("Saving coverage")
cov.stop()
Expand Down
7 changes: 7 additions & 0 deletions test/integration_tests/python/test_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,10 @@ def test_devicehandler(as_user, as_root, as_drone, api_db):

# clean up
api_db.devices.remove({'_id': 'test_drone'})


def test_config_version(as_user):
# get database schema version
r = as_user.get('/version')
assert r.ok
assert r.text == '' # not set yet
38 changes: 32 additions & 6 deletions test/integration_tests/python/test_jobs.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import copy

import bson


def test_jobs_access(as_user):
r = as_user.get('/jobs/next')
Expand All @@ -18,7 +20,7 @@ def test_jobs_access(as_user):
assert r.status_code == 403


def test_jobs(data_builder, as_user, as_admin, as_root):
def test_jobs(data_builder, as_user, as_admin, as_root, api_db):
gear = data_builder.create_gear()
invalid_gear = data_builder.create_gear(gear={'custom': {'flywheel': {'invalid': True}}})
acquisition = data_builder.create_acquisition()
Expand Down Expand Up @@ -70,6 +72,16 @@ def test_jobs(data_builder, as_user, as_admin, as_root):
r = as_root.post('/jobs/000000000000000000000000/logs', json=job_logs)
assert r.status_code == 404

# get job log as text w/o logs
r = as_admin.get('/jobs/' + job1_id + '/logs/text')
assert r.ok
assert r.text == '<span class="fd--1">No logs were found for this job.</span>'

# get job log as html w/o logs
r = as_admin.get('/jobs/' + job1_id + '/logs/html')
assert r.ok
assert r.text == '<span class="fd--1">No logs were found for this job.</span>'

# add job log
r = as_root.post('/jobs/' + job1_id + '/logs', json=job_logs)
assert r.ok
Expand All @@ -83,19 +95,33 @@ def test_jobs(data_builder, as_user, as_admin, as_root):
assert r.ok
assert len(r.json()['logs']) == 2

# add same logs again (for testing text/html logs)
r = as_root.post('/jobs/' + job1_id + '/logs', json=job_logs)
assert r.ok

# get job log as text
r = as_admin.get('/jobs/' + job1_id + '/logs/text')
assert r.ok
assert r.text == 2 * ''.join(log['msg'] for log in job_logs)

# get job log as html
r = as_admin.get('/jobs/' + job1_id + '/logs/html')
assert r.ok
assert r.text == 2 * ''.join('<span class="fd-{fd}">{msg}</span>\n'.format(**log) for log in job_logs)

# get job config
r = as_root.get('/jobs/' + job1_id + '/config.json')
assert r.ok

# try to update job (user may only cancel)
# root = true for as_admin, until thats fixed, using user
r = as_user.put('/jobs/' + job1_id, json={'test': 'invalid'})
assert r.status_code == 403

# try to cancel job w/o permission (different user)
r = as_user.put('/jobs/' + job1_id, json={'state': 'cancelled'})
assert r.status_code == 403

# try to update job (user may only cancel)
api_db.jobs.update_one({'_id': bson.ObjectId(job1_id)}, {'$set': {'origin.id': 'user@user.com'}})
r = as_user.put('/jobs/' + job1_id, json={'test': 'invalid'})
assert r.status_code == 403

# add job with implicit destination
job2 = copy.deepcopy(job_data)
del job2['destination']
Expand Down
161 changes: 139 additions & 22 deletions test/integration_tests/python/test_resolver.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
def test_resolver(data_builder, as_admin, as_public):
def path_in_result(path, result):
return [node.get('_id', node.get('name')) for node in result['path']] == path


def child_in_result(child, result):
return sum(all((k in c and c[k]==v) for k,v in child.iteritems()) for c in result['children']) == 1


def test_resolver(data_builder, as_admin, as_user, as_public, file_form):
# ROOT
# try accessing resolver w/o logging in
r = as_public.post('/resolve', json={'path': []})
assert r.status_code == 403
Expand All @@ -7,58 +16,166 @@ def test_resolver(data_builder, as_admin, as_public):
r = as_admin.post('/resolve', json={'path': 'test'})
assert r.status_code == 500

# resolve root
# resolve root (empty)
r = as_admin.post('/resolve', json={'path': []})
result = r.json()
assert r.ok
assert r.json()['path'] == []
assert result['path'] == []
assert result['children'] == []

# resolve root w/ group
# resolve root (1 group)
group = data_builder.create_group()
r = as_admin.post('/resolve', json={'path': []})
result = r.json()
assert r.ok
assert result['path'] == []
assert sum(child['_id'] == group for child in result['children']) == 1
assert all(child['node_type'] == 'group' for child in result['children'])
assert child_in_result({'_id': group, 'node_type': 'group'}, result)

# try to resolve non-existent group id
r = as_admin.post('/resolve', json={'path': ['non-existent-group-id']})
# try to resolve non-existent root/child
r = as_admin.post('/resolve', json={'path': ['child']})
assert r.status_code == 500

# resolve group

# GROUP
# try to resolve root/group as different (and non-root) user
r = as_user.post('/resolve', json={'path': [group]})
assert r.status_code == 403

# resolve root/group (empty)
r = as_admin.post('/resolve', json={'path': [group]})
result = r.json()
assert r.ok
assert [node['_id'] for node in result['path']] == [group]
assert path_in_result([group], result)
assert result['children'] == []

# resolve group w/ project
# resolve root/group (1 project)
project_label = 'test-resolver-project-label'
project = data_builder.create_project(label=project_label)
r = as_admin.post('/resolve', json={'path': [group]})
result = r.json()
assert r.ok
assert [node['_id'] for node in result['path']] == [group]
assert sum(child['_id'] == project for child in result['children']) == 1
assert all(child['node_type'] == 'project' for child in result['children'])
assert path_in_result([group], result)
assert child_in_result({'_id': project, 'node_type': 'project'}, result)

# try to resolve non-existent project label
r = as_admin.post('/resolve', json={'path': [group, 'non-existent-project-label']})
# try to resolve non-existent root/group/child
r = as_admin.post('/resolve', json={'path': [group, 'child']})
assert r.status_code == 500

# resolve project

# PROJECT
# resolve root/group/project (empty)
r = as_admin.post('/resolve', json={'path': [group, project_label]})
result = r.json()
assert r.ok
assert [node['_id'] for node in result['path']] == [group, project]
assert path_in_result([group, project], result)
assert result['children'] == []

# resolve project w/ session
# resolve root/group/project (1 file)
project_file = 'project_file'
r = as_admin.post('/projects/' + project + '/files', files=file_form(project_file))
assert r.ok
r = as_admin.post('/resolve', json={'path': [group, project_label]})
result = r.json()
assert r.ok
assert path_in_result([group, project], result)
assert child_in_result({'name': project_file, 'node_type': 'file'}, result)
assert len(result['children']) == 1

# resolve root/group/project (1 file, 1 session)
session_label = 'test-resolver-session-label'
session = data_builder.create_session(label=session_label)
r = as_admin.post('/resolve', json={'path': [group, project_label]})
result = r.json()
assert r.ok
assert [node['_id'] for node in result['path']] == [group, project]
assert sum(child['_id'] == session for child in result['children']) == 1
assert all(child['node_type'] == 'session' for child in result['children'])
assert path_in_result([group, project], result)
assert child_in_result({'_id': session, 'node_type': 'session'}, result)
assert len(result['children']) == 2

# resolve root/group/project/file
r = as_admin.post('/resolve', json={'path': [group, project_label, project_file]})
result = r.json()
assert r.ok
assert path_in_result([group, project, project_file], result)
assert result['children'] == []

# try to resolve non-existent root/group/project/child
r = as_admin.post('/resolve', json={'path': [group, project_label, 'child']})
assert r.status_code == 500


# SESSION
# resolve root/group/project/session (empty)
r = as_admin.post('/resolve', json={'path': [group, project_label, session_label]})
result = r.json()
assert r.ok
assert path_in_result([group, project, session], result)
assert result['children'] == []

# resolve root/group/project/session (1 file)
session_file = 'session_file'
r = as_admin.post('/sessions/' + session + '/files', files=file_form(session_file))
assert r.ok
r = as_admin.post('/resolve', json={'path': [group, project_label, session_label]})
result = r.json()
assert r.ok
assert path_in_result([group, project, session], result)
assert child_in_result({'name': session_file, 'node_type': 'file'}, result)
assert len(result['children']) == 1

# resolve root/group/project/session (1 file, 1 acquisition)
acquisition_label = 'test-resolver-acquisition-label'
acquisition = data_builder.create_acquisition(label=acquisition_label)
r = as_admin.post('/resolve', json={'path': [group, project_label, session_label]})
result = r.json()
assert r.ok
assert path_in_result([group, project, session], result)
assert child_in_result({'_id': acquisition, 'node_type': 'acquisition'}, result)
assert len(result['children']) == 2

# resolve root/group/project/session/file
r = as_admin.post('/resolve', json={'path': [group, project_label, session_label, session_file]})
result = r.json()
assert r.ok
assert path_in_result([group, project, session, session_file], result)
assert result['children'] == []

# try to resolve non-existent root/group/project/session/child
r = as_admin.post('/resolve', json={'path': [group, project_label, session_label, 'child']})
assert r.status_code == 500


# ACQUISITION
# resolve root/group/project/session/acquisition (empty)
r = as_admin.post('/resolve', json={'path': [group, project_label, session_label, acquisition_label]})
result = r.json()
assert r.ok
assert path_in_result([group, project, session, acquisition], result)
assert result['children'] == []

# resolve root/group/project/session/acquisition (1 file)
acquisition_file = 'acquisition_file'
r = as_admin.post('/acquisitions/' + acquisition + '/files', files=file_form(acquisition_file))
assert r.ok
r = as_admin.post('/resolve', json={'path': [group, project_label, session_label, acquisition_label]})
result = r.json()
assert r.ok
assert path_in_result([group, project, session, acquisition], result)
assert child_in_result({'name': acquisition_file, 'node_type': 'file'}, result)
assert len(result['children']) == 1

# resolve root/group/project/session/acquisition/file
r = as_admin.post('/resolve', json={'path': [group, project_label, session_label, acquisition_label, acquisition_file]})
result = r.json()
assert r.ok
assert path_in_result([group, project, session, acquisition, acquisition_file], result)
assert result['children'] == []

# try to resolve non-existent root/group/project/session/acquisition/child
r = as_admin.post('/resolve', json={'path': [group, project_label, session_label, acquisition_label, 'child']})
assert r.status_code == 500


# FILE
# try to resolve non-existent (also invalid) root/group/project/session/acquisition/file/child
r = as_admin.post('/resolve', json={'path': [group, project_label, session_label, acquisition_label, acquisition_file, 'child']})
assert r.status_code == 500
2 changes: 2 additions & 0 deletions test/integration_tests/requirements-integration-test.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ coverage==4.0.3
coveralls==1.1
mock==2.0.0
mongomock==3.8.0
newrelic==2.60.0.46
pdbpp==0.8.3
pylint==1.5.3
pytest-cov==2.2.0
pytest-mock==1.6.0
pytest-watch==3.8.0
pytest==2.8.5
requests_mock==1.3.0
Expand Down
Loading