From bf37139bfb863c94c491fcebb1db82ba297c155d Mon Sep 17 00:00:00 2001 From: Renzo Frigato Date: Mon, 1 Feb 2016 15:05:19 -0800 Subject: [PATCH 1/8] adapt tests to the paster app server --- test/integration_tests/test_collection.py | 60 +++++---- test/integration_tests/test_containers.py | 107 ++++++++++------ test/integration_tests/test_download.py | 137 +++++++++++++++++++++ test/integration_tests/test_errors.py | 6 +- test/integration_tests/test_groups.py | 23 ++-- test/integration_tests/test_notes.py | 66 +++++----- test/integration_tests/test_permissions.py | 76 +++++++++--- test/integration_tests/test_roles.py | 113 ++++++++++++----- test/integration_tests/test_tags.py | 67 ++++++---- test/integration_tests/test_users.py | 14 +-- 10 files changed, 488 insertions(+), 181 deletions(-) create mode 100644 test/integration_tests/test_download.py diff --git a/test/integration_tests/test_collection.py b/test/integration_tests/test_collection.py index 8d34581d2..1a44b83a5 100644 --- a/test/integration_tests/test_collection.py +++ b/test/integration_tests/test_collection.py @@ -1,5 +1,6 @@ import requests import json +import time import logging log = logging.getLogger(__name__) @@ -7,27 +8,36 @@ log.addHandler(sh) log.setLevel(logging.INFO) -import warnings - -warnings.filterwarnings('ignore') - from nose.tools import with_setup import pymongo from bson.objectid import ObjectId -db = pymongo.MongoClient('mongodb://localhost/scitran').get_default_database() - -base_url = 'https://localhost:8443/api' +db = pymongo.MongoClient('mongodb://localhost:9001/scitran').get_default_database() +adm_user = 'test@user.com' +base_url = 'http://localhost:8080/api' test_data = type('',(object,),{})() def setup_db(): + global session + session = requests.Session() + session.params = { + 'user': adm_user, + 'root': True + } + test_data.group_id = 'test_group_' + str(int(time.time()*1000)) payload = { - 'group': 'unknown', - 'label': 'SciTran/Testing', + '_id': test_data.group_id + } + payload = json.dumps(payload) + r = session.post(base_url + '/groups', data=payload) + assert r.ok + payload = { + 'group': test_data.group_id, + 'label': 'test_project', 'public': False } payload = json.dumps(payload) - r = requests.post(base_url + '/projects?user=admin@user.com&root=true', data=payload, verify=False) + r = session.post(base_url + '/projects', data=payload) test_data.pid = json.loads(r.content)['_id'] assert r.ok log.debug('pid = \'{}\''.format(test_data.pid)) @@ -38,7 +48,7 @@ def setup_db(): 'public': False } payload = json.dumps(payload) - r = requests.post(base_url + '/sessions?user=admin@user.com&root=true', data=payload, verify=False) + r = session.post(base_url + '/sessions', data=payload) assert r.ok test_data.sid = json.loads(r.content)['_id'] log.debug('sid = \'{}\''.format(test_data.sid)) @@ -49,32 +59,34 @@ def setup_db(): 'public': False } payload = json.dumps(payload) - r = requests.post(base_url + '/acquisitions?user=admin@user.com&root=true', data=payload, verify=False) + r = session.post(base_url + '/acquisitions', data=payload) assert r.ok test_data.aid = json.loads(r.content)['_id'] log.debug('aid = \'{}\''.format(test_data.aid)) def teardown_db(): - r = requests.delete(base_url + '/acquisitions/' + test_data.aid + '?user=admin@user.com&root=true', verify=False) + session.params['root'] = True + r = session.delete(base_url + '/acquisitions/' + test_data.aid) assert r.ok - r = requests.delete(base_url + '/sessions/' + test_data.sid + '?user=admin@user.com&root=true', verify=False) + r = session.delete(base_url + '/sessions/' + test_data.sid) assert r.ok - r = requests.delete(base_url + '/projects/' + test_data.pid + '?user=admin@user.com&root=true', verify=False) + r = session.delete(base_url + '/projects/' + test_data.pid) assert r.ok @with_setup(setup_db, teardown_db) def test_collections(): payload = { - 'curator': 'admin@user.com', - 'label': 'SciTran/Testing', - 'public': True + 'curator': adm_user, + 'label': 'test_collection_'+ str(int(time.time())) , + 'public': False } - r = requests.post(base_url + '/collections?user=admin@user.com', data=json.dumps(payload), verify=False) + session.params['root'] = False + r = session.post(base_url + '/collections', data=json.dumps(payload)) assert r.ok _id = json.loads(r.content)['_id'] log.debug('_id = \'{}\''.format(_id)) - r = requests.get(base_url + '/collections/' + _id + '?user=admin@user.com', verify=False) + r = session.get(base_url + '/collections/' + _id) assert r.ok payload = { 'contents':{ @@ -86,9 +98,9 @@ def test_collections(): 'operation': 'add' } } - r = requests.put(base_url + '/collections/' + _id + '?user=admin@user.com', data=json.dumps(payload), verify=False) + r = session.put(base_url + '/collections/' + _id, data=json.dumps(payload)) assert r.ok - r = requests.get(base_url + '/collections/' + _id + '/acquisitions?session=' + test_data.sid + '&user=admin@user.com', verify=False) + r = session.get(base_url + '/collections/' + _id + '/acquisitions?session=' + test_data.sid) assert r.ok coll_acq_id= json.loads(r.content)[0]['_id'] assert coll_acq_id == test_data.aid @@ -97,9 +109,9 @@ def test_collections(): for ac in acs: assert len(ac['collections']) == 1 assert ac['collections'][0] == ObjectId(_id) - r = requests.delete(base_url + '/collections/' + _id + '?user=admin@user.com', verify=False) + r = session.delete(base_url + '/collections/' + _id) assert r.ok - r = requests.get(base_url + '/collections/' + _id + '?user=admin@user.com', verify=False) + r = session.get(base_url + '/collections/' + _id) assert r.status_code == 404 acs = db.acquisitions.find({'_id': {'$in': acq_ids}}) for ac in acs: diff --git a/test/integration_tests/test_containers.py b/test/integration_tests/test_containers.py index f6e2887df..cdfdec9e2 100644 --- a/test/integration_tests/test_containers.py +++ b/test/integration_tests/test_containers.py @@ -1,43 +1,79 @@ import requests import json +import time +from nose.tools import with_setup import logging + log = logging.getLogger(__name__) sh = logging.StreamHandler() log.addHandler(sh) -requests.packages.urllib3.disable_warnings() +base_url = 'http://localhost:8080/api' +adm_user = 'test@user.com' +test_data = type('',(object,),{})() + +def setup_db(): + global session + session = requests.Session() + # all the requests will be performed as root + session.params = { + 'user': adm_user, + 'root': True + } + + # Create a group + test_data.group_id = 'test_group_' + str(int(time.time()*1000)) + payload = { + '_id': test_data.group_id + } + payload = json.dumps(payload) + r = session.post(base_url + '/groups', data=payload) + assert r.ok + test_data.group_id_1 = 'test_group_' + str(int(time.time()*1000)) + payload = { + '_id': test_data.group_id_1 + } + payload = json.dumps(payload) + r = session.post(base_url + '/groups', data=payload) + assert r.ok -base_url = 'https://localhost:8443/api' +def teardown_db(): + r = session.delete(base_url + '/groups/' + test_data.group_id) + assert r.ok + r = session.delete(base_url + '/groups/' + test_data.group_id_1) + assert r.ok +@with_setup(setup_db, teardown_db) def test_projects(): payload = { - 'group': 'unknown', - 'label': 'SciTran/Testing', + 'group': test_data.group_id, + 'label': 'test_project', 'public': False } payload = json.dumps(payload) - r = requests.post(base_url + '/projects?user=admin@user.com&root=true', data=payload, verify=False) + r = session.post(base_url + '/projects', data=payload) assert r.ok _id = json.loads(r.content)['_id'] - r = requests.get(base_url + '/projects/' + _id + '?user=admin@user.com&root=true', verify=False) + r = session.get(base_url + '/projects/' + _id) assert r.ok payload = { - 'group': 'scitran', + 'group': test_data.group_id_1, } payload = json.dumps(payload) - r = requests.put(base_url + '/projects/' + _id + '?user=admin@user.com&root=true', data=payload, verify=False) + r = session.put(base_url + '/projects/' + _id, data=payload) assert r.ok - r = requests.delete(base_url + '/projects/' + _id + '?user=admin@user.com&root=true', verify=False) + r = session.delete(base_url + '/projects/' + _id) assert r.ok +@with_setup(setup_db, teardown_db) def test_sessions(): payload = { - 'group': 'unknown', - 'label': 'SciTran/Testing', + 'group': test_data.group_id, + 'label': 'test_project', 'public': False } payload = json.dumps(payload) - r = requests.post(base_url + '/projects?user=admin@user.com&root=true', data=payload, verify=False) + r = session.post(base_url + '/projects', data=payload) assert r.ok pid = json.loads(r.content)['_id'] payload = { @@ -46,43 +82,44 @@ def test_sessions(): 'public': False } payload = json.dumps(payload) - r = requests.post(base_url + '/sessions?user=admin@user.com&root=true', data=payload, verify=False) + r = session.post(base_url + '/sessions', data=payload) assert r.ok _id = json.loads(r.content)['_id'] - r = requests.get(base_url + '/sessions/' + _id + '?user=admin@user.com&root=true', verify=False) + r = session.get(base_url + '/sessions/' + _id) assert r.ok payload = { - 'group': 'unknown', - 'label': 'SciTran/Testing 2', + 'group': test_data.group_id, + 'label': 'test_project_1', 'public': False } payload = json.dumps(payload) - r = requests.post(base_url + '/projects?user=admin@user.com&root=true', data=payload, verify=False) + r = session.post(base_url + '/projects', data=payload) new_pid = json.loads(r.content)['_id'] assert r.ok payload = { 'project': new_pid, } payload = json.dumps(payload) - r = requests.put(base_url + '/sessions/' + _id + '?user=admin@user.com&root=true', data=payload, verify=False) + r = session.put(base_url + '/sessions/' + _id, data=payload) assert r.ok - r = requests.delete(base_url + '/sessions/' + _id + '?user=admin@user.com&root=true', verify=False) + r = session.delete(base_url + '/sessions/' + _id) assert r.ok - r = requests.get(base_url + '/sessions/' + _id + '?user=admin@user.com&root=true', verify=False) + r = session.get(base_url + '/sessions/' + _id) assert r.status_code == 404 - r = requests.delete(base_url + '/projects/' + pid + '?user=admin@user.com&root=true', verify=False) + r = session.delete(base_url + '/projects/' + pid) assert r.ok - r = requests.delete(base_url + '/projects/' + new_pid + '?user=admin@user.com&root=true', verify=False) + r = session.delete(base_url + '/projects/' + new_pid) assert r.ok +@with_setup(setup_db, teardown_db) def test_acquisitions(): payload = { - 'group': 'unknown', - 'label': 'SciTran/Testing', + 'group': test_data.group_id, + 'label': 'test_project', 'public': False } payload = json.dumps(payload) - r = requests.post(base_url + '/projects?user=admin@user.com&root=true', data=payload, verify=False) + r = session.post(base_url + '/projects', data=payload) assert r.ok pid = json.loads(r.content)['_id'] payload = { @@ -91,7 +128,7 @@ def test_acquisitions(): 'public': False } payload = json.dumps(payload) - r = requests.post(base_url + '/sessions?user=admin@user.com&root=true', data=payload, verify=False) + r = session.post(base_url + '/sessions', data=payload) assert r.ok sid = json.loads(r.content)['_id'] @@ -101,7 +138,7 @@ def test_acquisitions(): 'public': False } payload = json.dumps(payload) - r = requests.post(base_url + '/sessions?user=admin@user.com&root=true', data=payload, verify=False) + r = session.post(base_url + '/sessions', data=payload) assert r.ok new_sid = json.loads(r.content)['_id'] @@ -111,27 +148,27 @@ def test_acquisitions(): 'public': False } payload = json.dumps(payload) - r = requests.post(base_url + '/acquisitions?user=admin@user.com&root=true', data=payload, verify=False) + r = session.post(base_url + '/acquisitions', data=payload) assert r.ok aid = json.loads(r.content)['_id'] - r = requests.get(base_url + '/acquisitions/' + aid + '?user=admin@user.com&root=true', verify=False) + r = session.get(base_url + '/acquisitions/' + aid) assert r.ok payload = { 'session': new_sid } payload = json.dumps(payload) - r = requests.put(base_url + '/acquisitions/' + aid + '?user=admin@user.com&root=true', data=payload, verify=False) + r = session.put(base_url + '/acquisitions/' + aid, data=payload) assert r.ok - r = requests.delete(base_url + '/acquisitions/' + aid + '?user=admin@user.com&root=true', verify=False) + r = session.delete(base_url + '/acquisitions/' + aid) assert r.ok - r = requests.get(base_url + '/acquisitions/' + aid + '?user=admin@user.com&root=true', verify=False) + r = session.get(base_url + '/acquisitions/' + aid) assert r.status_code == 404 - r = requests.delete(base_url + '/sessions/' + sid + '?user=admin@user.com&root=true', verify=False) + r = session.delete(base_url + '/sessions/' + sid) assert r.ok - r = requests.delete(base_url + '/sessions/' + new_sid + '?user=admin@user.com&root=true', verify=False) + r = session.delete(base_url + '/sessions/' + new_sid) assert r.ok - r = requests.delete(base_url + '/projects/' + pid + '?user=admin@user.com&root=true', verify=False) + r = session.delete(base_url + '/projects/' + pid) assert r.ok diff --git a/test/integration_tests/test_download.py b/test/integration_tests/test_download.py new file mode 100644 index 000000000..4f6c49307 --- /dev/null +++ b/test/integration_tests/test_download.py @@ -0,0 +1,137 @@ +import requests +import json +import time +import logging +from nose.tools import with_setup + +log = logging.getLogger(__name__) +sh = logging.StreamHandler() +log.addHandler(sh) +log.setLevel(logging.INFO) + + +base_url = 'http://localhost:8080/api' +test_data = type('',(object,),{})() + +session = None + +def setup_download(): + global session + session = requests.Session() + # all the requests will be performed as root + session.params = { + 'user': 'test@user.com', + 'root': True + } + + # Create a group + test_data.group_id = 'test_group_' + str(int(time.time()*1000)) + payload = { + '_id': test_data.group_id + } + payload = json.dumps(payload) + r = session.post(base_url + '/groups', data=payload) + assert r.ok + + # Create a project + payload = { + 'group': test_data.group_id, + 'label': 'scitran_testing', + 'public': False + } + payload = json.dumps(payload) + r = session.post(base_url + '/projects', data=payload) + test_data.pid = json.loads(r.content)['_id'] + assert r.ok + log.debug('pid = \'{}\''.format(test_data.pid)) + + # Create a session + payload = { + 'project': test_data.pid, + 'label': 'session_testing', + 'public': False + } + payload = json.dumps(payload) + r = session.post(base_url + '/sessions', data=payload) + assert r.ok + test_data.sid = json.loads(r.content)['_id'] + log.debug('sid = \'{}\''.format(test_data.sid)) + + # Create an acquisition + payload = { + 'session': test_data.sid, + 'label': 'acq_testing', + 'public': False + } + payload = json.dumps(payload) + r = session.post(base_url + '/acquisitions', data=payload) + assert r.ok + test_data.aid = json.loads(r.content)['_id'] + log.debug('aid = \'{}\''.format(test_data.aid)) + + ## multiform fields for the file upload + files = {'file': ('test.csv', 'some,data,to,send\nanother,row,to,send\n'), + 'tags': ('', '["incomplete"]'), + 'metadata': ('', + '{"group": {"_id": "scitran"}, ' \ + '"project": {"label": "Testdata"}, ' \ + '"session": {"uid": "1.2.840.113619.6.353.10437158128305161617400354036593525848"}, ' \ + '"file": {"type": "nifti"}, ' + '"acquisition": {"uid": "1.2.840.113619.2.353.4120.7575399.14591.1403393566.658_1", ' \ + '"timestamp": "1970-01-01T00:00:00", ' \ + '"label": "Screen Save", ' \ + '"instrument": "MRI", ' \ + '"measurement": "screensave", ' \ + '"timezone": "America/Los_Angeles"}, ' \ + '"subject": {"code": "ex7236"}}' + )} + + # upload the same file to each container created in the test + session.post(base_url + '/acquisitions/' + test_data.aid +'/files', files=files) + session.post(base_url + '/sessions/' + test_data.sid +'/files', files=files) + session.post(base_url + '/projects/' + test_data.pid +'/files', files=files) + + +def teardown_download(): + success = True + # remove all the container created in the test + r = session.delete(base_url + '/acquisitions/' + test_data.aid) + success = success and r.ok + r = session.delete(base_url + '/sessions/' + test_data.sid) + success = success and r.ok + r = session.delete(base_url + '/projects/' + test_data.pid) + success = success and r.ok + r = session.delete(base_url + '/groups/' + test_data.group_id) + success = success and r.ok + session.close() + if not success: + log.error('error in the teardown. These containers may have not been removed.') + log.error(str(test_data.__dict__)) + + +@with_setup(setup_download, teardown_download) +def test_download(): + # Retrieve a ticket for a batch download + payload = { + 'optional': False, + 'nodes': [ + { + 'level': 'project', + '_id': test_data.pid + } + ] + } + payload = json.dumps(payload) + r = session.post(base_url + '/download', data=payload) + assert r.ok + + # Perform the download + ticket = json.loads(r.content)['ticket'] + r = session.get(base_url + '/download', params={'ticket': ticket}) + assert r.ok + # Save the tar to a file if successful + f = open('test_download.tar', 'w') + f.write(r.content) + f.close() + + diff --git a/test/integration_tests/test_errors.py b/test/integration_tests/test_errors.py index 84a884618..01cdffe06 100644 --- a/test/integration_tests/test_errors.py +++ b/test/integration_tests/test_errors.py @@ -6,10 +6,10 @@ log.addHandler(sh) import warnings warnings.filterwarnings('ignore') -base_url = 'https://localhost:8443/api' +base_url = 'http://localhost:8080/api' import pymongo -db = pymongo.MongoClient('mongodb://localhost/scitran').get_default_database() +db = pymongo.MongoClient('mongodb://localhost:9001/scitran').get_default_database() projects = db.projects def test_extra_param(): @@ -20,7 +20,7 @@ def test_extra_param(): 'extra_param': 'some_value' } payload = json.dumps(payload) - r = requests.post(base_url + '/projects?user=admin@user.com&root=true', data=payload, verify=False) + r = requests.post(base_url + '/projects?user=test@user.com&root=true', data=payload) assert r.status_code == 400 r = projects.delete_many({'label': 'SciTran/Testing'}) assert r.deleted_count == 0 diff --git a/test/integration_tests/test_groups.py b/test/integration_tests/test_groups.py index 170f6ceb6..75b204b7e 100644 --- a/test/integration_tests/test_groups.py +++ b/test/integration_tests/test_groups.py @@ -1,31 +1,36 @@ import requests import json +import time import logging log = logging.getLogger(__name__) sh = logging.StreamHandler() log.addHandler(sh) -requests.packages.urllib3.disable_warnings() - -base_url = 'https://localhost:8443/api' +base_url = 'http://localhost:8080/api' def test_groups(): - _id = 'test' - r = requests.get(base_url + '/groups/' + _id + '?user=admin@user.com&root=true', verify=False) + session = requests.Session() + # all the requests will be performed as root + session.params = { + 'user': 'test@user.com', + 'root': True + } + _id = 'test_group_' + str(int(time.time()*1000)) + r = session.get(base_url + '/groups/' + _id) assert r.status_code == 404 payload = { '_id': _id } payload = json.dumps(payload) - r = requests.post(base_url + '/groups?user=admin@user.com&root=true', data=payload, verify=False) + r = session.post(base_url + '/groups', data=payload) assert r.ok - r = requests.get(base_url + '/groups/' + _id + '?user=admin@user.com&root=true', verify=False) + r = session.get(base_url + '/groups/' + _id) assert r.ok payload = { 'name': 'Test group', } payload = json.dumps(payload) - r = requests.put(base_url + '/groups/' + _id + '?user=admin@user.com&root=true', data=payload, verify=False) + r = session.put(base_url + '/groups/' + _id, data=payload) assert r.ok - r = requests.delete(base_url + '/groups/' + _id + '?user=admin@user.com&root=true', verify=False) + r = session.delete(base_url + '/groups/' + _id) assert r.ok diff --git a/test/integration_tests/test_notes.py b/test/integration_tests/test_notes.py index 42188ba62..4ab669d92 100644 --- a/test/integration_tests/test_notes.py +++ b/test/integration_tests/test_notes.py @@ -1,6 +1,6 @@ import requests import json -import warnings +import time from nose.tools import with_setup import logging @@ -8,12 +8,10 @@ sh = logging.StreamHandler() log.addHandler(sh) log.setLevel(logging.INFO) -warnings.filterwarnings('ignore') -adm_user = 'admin@user.com' -user = 'test@user.com' +adm_user = 'test@user.com' test_data = type('',(object,),{})() -base_url = 'https://localhost:8443/api' +base_url = 'http://localhost:8080/api' def _build_url(_id=None, requestor=adm_user): if _id is None: @@ -22,56 +20,66 @@ def _build_url(_id=None, requestor=adm_user): url = test_data.proj_url + '/' + _id + '?user=' + requestor return url - def setup_db(): + global session + session = requests.Session() + # all the requests will be performed as root + session.params = { + 'user': adm_user, + 'root': True + } + + # Create a group + test_data.group_id = 'test_group_' + str(int(time.time()*1000)) payload = { - 'group': 'unknown', - 'label': 'SciTran/Testing', + '_id': test_data.group_id + } + payload = json.dumps(payload) + r = session.post(base_url + '/groups', data=payload) + assert r.ok + payload = { + 'group': test_data.group_id, + 'label': 'test_project', 'public': False } payload = json.dumps(payload) - r = requests.post(base_url + '/projects?user=admin@user.com&root=true', data=payload, verify=False) + r = session.post(base_url + '/projects', data=payload) test_data.pid = json.loads(r.content)['_id'] assert r.ok log.debug('pid = \'{}\''.format(test_data.pid)) test_data.proj_url = base_url + '/projects/{}/notes'.format(test_data.pid) - data = { - '_id': user, - 'site': 'local', - 'access': 'rw' - } - url = base_url + '/projects/' + test_data.pid + '/permissions?user=admin@user.com&root=true' - r = requests.post(url, data=json.dumps(data), verify=False) - assert r.ok def teardown_db(): - r = requests.delete(base_url + '/projects/' + test_data.pid + '?user=admin@user.com&root=true', verify=False) + r = session.delete(base_url + '/projects/' + test_data.pid) + assert r.ok + r = session.delete(base_url + '/groups/' + test_data.group_id) assert r.ok @with_setup(setup_db, teardown_db) def test_notes(): - url_post = _build_url(requestor=user) - data = {'user': user, 'text':'test note'} - r = requests.post(url_post, data=json.dumps(data), verify=False) + url_post = test_data.proj_url + + data = {'text':'test note'} + r = session.post(url_post, data=json.dumps(data)) assert r.ok - r = requests.get(base_url + '/projects/{}?user={}'.format(test_data.pid, adm_user), verify=False) + r = session.get(base_url + '/projects/{}?user={}'.format(test_data.pid, adm_user)) assert r.ok p = json.loads(r.content) assert len(p['notes']) == 1 - assert p['notes'][0]['user'] == user + assert p['notes'][0]['user'] == adm_user note_id = p['notes'][0]['_id'] - url_get = _build_url(note_id, user) - r = requests.get(url_get, verify=False) + url_get = test_data.proj_url + '/' + note_id + r = session.get(url_get) assert r.ok assert json.loads(r.content)['_id'] == note_id data = {'text':'modified test note'} - r = requests.put(url_get, data=json.dumps(data), verify=False) + r = session.put(url_get, data=json.dumps(data)) assert r.ok - r = requests.get(url_get, verify=False) + r = session.get(url_get) assert r.ok assert json.loads(r.content)['text'] == 'modified test note' - r = requests.delete(url_get, verify=False) + r = session.delete(url_get) assert r.ok - r = requests.get(url_get, verify=False) + r = session.get(url_get) assert r.status_code == 404 diff --git a/test/integration_tests/test_permissions.py b/test/integration_tests/test_permissions.py index f26cf736b..8ba38f4e8 100644 --- a/test/integration_tests/test_permissions.py +++ b/test/integration_tests/test_permissions.py @@ -1,6 +1,6 @@ import requests import json -import warnings +import time from nose.tools import with_setup import logging @@ -8,12 +8,13 @@ sh = logging.StreamHandler() log.addHandler(sh) log.setLevel(logging.INFO) -warnings.filterwarnings('ignore') -adm_user = 'admin@user.com' -user = 'test@user.com' +adm_user = 'test@user.com' +user = 'other@user.com' +user1 = 'other1@user.com' test_data = type('',(object,),{})() -base_url = 'https://localhost:8443/api' +base_url = 'http://localhost:8080/api' +session = None def _build_url(_id=None, requestor=adm_user, site='local'): if _id is None: @@ -24,36 +25,55 @@ def _build_url(_id=None, requestor=adm_user, site='local'): def setup_db(): + global session + session = requests.Session() + # all the requests will be performed as root + session.params = { + 'user': adm_user, + 'root': True + } + + # Create a group + test_data.group_id = 'test_group_' + str(int(time.time()*1000)) + payload = { + '_id': test_data.group_id + } + payload = json.dumps(payload) + r = session.post(base_url + '/groups', data=payload) + assert r.ok payload = { - 'group': 'unknown', - 'label': 'SciTran/Testing', + 'group': test_data.group_id, + 'label': 'test_project', 'public': False } payload = json.dumps(payload) - r = requests.post(base_url + '/projects?user=admin@user.com&root=true', data=payload, verify=False) + r = session.post(base_url + '/projects', data=payload) test_data.pid = json.loads(r.content)['_id'] assert r.ok log.debug('pid = \'{}\''.format(test_data.pid)) test_data.proj_url = base_url + '/projects/{}/permissions'.format(test_data.pid) def teardown_db(): - r = requests.delete(base_url + '/projects/' + test_data.pid + '?user=admin@user.com&root=true', verify=False) + r = session.delete(base_url + '/projects/' + test_data.pid) + assert r.ok + r = session.delete(base_url + '/groups/' + test_data.group_id) assert r.ok @with_setup(setup_db, teardown_db) def test_permissions(): url_post = _build_url() url_get = _build_url(user) - r = requests.get(url_get, verify=False) + url_get_1 = _build_url(user1) + r = requests.get(url_get) assert r.status_code == 404 data = { '_id': user, 'site': 'local', 'access': 'ro' } - r = requests.post(url_post, data = json.dumps(data), verify=False) + r = requests.post(url_post, data = json.dumps(data)) assert r.ok - r = requests.get(url_get, verify=False) + r = requests.get(url_get) assert r.ok content = json.loads(r.content) assert content['_id'] == user @@ -62,15 +82,33 @@ def test_permissions(): data = { 'access': 'admin' } - r = requests.put(url_get, data = json.dumps(data), verify=False) + r = requests.put(url_get, data = json.dumps(data)) assert r.ok - r = requests.get(url_get, verify=False) + data = { + '_id': user1, + 'site': 'local', + 'access': 'ro' + } + r = requests.post(url_post, data = json.dumps(data)) + assert r.ok + data = { + '_id': user + } + r = requests.put(url_get_1, data = json.dumps(data)) + assert r.status_code == 404 + data = { + 'site': 'another' + } + r = requests.put(url_get_1, data = json.dumps(data)) + assert r.ok + url_get_1 = _build_url(user1, site='another') + r = requests.get(url_get_1) assert r.ok content = json.loads(r.content) - assert content['_id'] == user - assert content['site'] == 'local' - assert content['access'] == 'admin' - r = requests.delete(url_get, verify=False) + assert content['_id'] == user1 + assert content['site'] == 'another' + assert content['access'] == 'ro' + r = requests.delete(url_get_1) assert r.ok - r = requests.get(url_get, verify=False) + r = requests.get(url_get_1) assert r.status_code == 404 diff --git a/test/integration_tests/test_roles.py b/test/integration_tests/test_roles.py index e577792a9..1c45a859a 100644 --- a/test/integration_tests/test_roles.py +++ b/test/integration_tests/test_roles.py @@ -1,15 +1,56 @@ import requests +import os import json -from pprint import pprint +import time +from nose.tools import with_setup -import warnings -warnings.filterwarnings('ignore') +base_url = 'http://localhost:8080/api' +adm_user = 'test@user.com' +user = 'other@user.com' +test_data = type('',(object,),{})() -base_url = 'https://localhost:8443/api/groups/scitran/roles' -def _build_url_and_payload(method, user, access, requestor, site='local'): +def setup_db(): + global session + session = requests.Session() + # all the requests will be performed as root + session.params = { + 'user': adm_user, + 'root': True + } + + # Create a group + test_data.group_id = 'test_group_' + str(int(time.time()*1000)) + payload = { + '_id': test_data.group_id + } + payload = json.dumps(payload) + r = session.post(base_url + '/groups', data=payload) + assert r.ok + payload = { + '_id': user, + 'firstname': 'Other', + 'lastname': 'User', + } + payload = json.dumps(payload) + r = session.post(base_url + '/users', data=payload) + assert r.ok + session.params = {} + +def teardown_db(): + session.params = { + 'user': adm_user, + 'root': True + } + r = session.delete(base_url + '/groups/' + test_data.group_id) + assert r.ok + r = session.delete(base_url + '/users/' + user) + assert r.ok + +def _build_url_and_payload(method, user, access, site='local'): + + url = os.path.join(base_url, 'groups', test_data.group_id, 'roles') if method == 'POST': - url = base_url + '?user=' + requestor payload = { '_id': user, 'site': site, @@ -17,45 +58,57 @@ def _build_url_and_payload(method, user, access, requestor, site='local'): } return url, json.dumps(payload) else: - url = base_url + '/' + site + '/' + user + '?user=' + requestor - return url, None - -adm_user = 'admin@user.com' -user = 'test@user.com' + return os.path.join(url, site, user), None +@with_setup(setup_db, teardown_db) def test_roles(): - url_get, _ = _build_url_and_payload('GET', user, None, adm_user) - r = requests.get(url_get, verify=False) + session.params = { + 'user': adm_user + } + url_get, _ = _build_url_and_payload('GET', user, None) + r = session.get(url_get) assert r.status_code == 404 - url_post, payload = _build_url_and_payload('POST', user, 'rw', adm_user) - r = requests.post(url_post, data=payload, verify=False) + url_post, payload = _build_url_and_payload('POST', user, 'rw') + r = session.post(url_post, data=payload) assert r.ok - r = requests.get(url_get, verify=False) + r = session.get(url_get) assert r.ok content = json.loads(r.content) assert content['access'] == 'rw' assert content['_id'] == user - - url_get_not_auth, _ = _build_url_and_payload('GET', adm_user, None, user) - r = requests.get(url_get_not_auth, verify=False) + session.params = { + 'user': user + } + url_get_not_auth, _ = _build_url_and_payload('GET', adm_user, None) + r = session.get(url_get_not_auth) assert r.status_code == 403 - + session.params = { + 'user': adm_user + } payload = json.dumps({'access':'admin'}) - r = requests.put(url_get, data=payload, verify=False) + r = session.put(url_get, data=payload) assert r.ok - - r = requests.get(url_get_not_auth, verify=False) + session.params = { + 'user': user + } + r = session.get(url_get_not_auth) assert r.ok - + session.params = { + 'user': adm_user + } payload = json.dumps({'access':'rw'}) - r = requests.put(url_get, data=payload, verify=False) + r = session.put(url_get, data=payload) assert r.ok - - r = requests.get(url_get_not_auth, verify=False) + session.params = { + 'user': user + } + r = session.get(url_get_not_auth) assert r.status_code == 403 - - r = requests.delete(url_get, verify=False) + session.params = { + 'user': adm_user + } + r = session.delete(url_get) assert r.ok - r = requests.get(url_get, verify=False) + r = session.get(url_get) assert r.status_code == 404 diff --git a/test/integration_tests/test_tags.py b/test/integration_tests/test_tags.py index eb19c8a17..8d337c663 100644 --- a/test/integration_tests/test_tags.py +++ b/test/integration_tests/test_tags.py @@ -1,6 +1,6 @@ import requests import json -import warnings +import time from nose.tools import with_setup import logging @@ -8,37 +8,54 @@ sh = logging.StreamHandler() log.addHandler(sh) log.setLevel(logging.INFO) -warnings.filterwarnings('ignore') adm_user = 'admin@user.com' test_data = type('',(object,),{})() -base_url = 'https://localhost:8443/api' +base_url = 'http://localhost:8080/api' +session = None def _build_url_and_payload(method, tag, newtag=None, requestor=adm_user): if method == 'POST': - url = test_data.proj_url + '?user=' + requestor + url = test_data.proj_url payload = json.dumps({'value': tag}) else: - url = test_data.proj_url + '/' + tag + '?user=' + requestor + url = test_data.proj_url + '/' + tag payload = json.dumps({'value': newtag}) return url, payload - def setup_db(): + global session + session = requests.Session() + # all the requests will be performed as root + session.params = { + 'user': 'test@user.com', + 'root': True + } + + # Create a group + test_data.group_id = 'test_group_' + str(int(time.time()*1000)) + payload = { + '_id': test_data.group_id + } + payload = json.dumps(payload) + r = session.post(base_url + '/groups', data=payload) + assert r.ok payload = { - 'group': 'unknown', - 'label': 'SciTran/Testing', + 'group': test_data.group_id, + 'label': 'test_project', 'public': False } payload = json.dumps(payload) - r = requests.post(base_url + '/projects?user=admin@user.com&root=true', data=payload, verify=False) + r = session.post(base_url + '/projects', data=payload) test_data.pid = json.loads(r.content)['_id'] assert r.ok log.debug('pid = \'{}\''.format(test_data.pid)) test_data.proj_url = base_url + '/projects/{}/tags'.format(test_data.pid) def teardown_db(): - r = requests.delete(base_url + '/projects/' + test_data.pid + '?user=admin@user.com&root=true', verify=False) + r = session.delete(base_url + '/projects/' + test_data.pid) + assert r.ok + r = session.delete(base_url + '/groups/' + test_data.group_id) assert r.ok @with_setup(setup_db, teardown_db) @@ -50,45 +67,45 @@ def test_tags(): url_get_new, _ = _build_url_and_payload('GET', new_tag) url_get_other, _ = _build_url_and_payload('GET', other_tag) - r = requests.get(url_get_tag, verify=False) + r = session.get(url_get_tag) assert r.status_code == 404 url_post, payload = _build_url_and_payload('POST', tag) - r = requests.post(url_post, data=payload, verify=False) + r = session.post(url_post, data=payload) assert r.ok - r = requests.get(url_get_tag, verify=False) + r = session.get(url_get_tag) assert r.ok assert json.loads(r.content) == tag url_post, payload = _build_url_and_payload('POST', new_tag) - r = requests.post(url_post, data=payload, verify=False) + r = session.post(url_post, data=payload) assert r.ok url_post, payload = _build_url_and_payload('POST', new_tag) - r = requests.post(url_post, data=payload, verify=False) + r = session.post(url_post, data=payload) assert r.status_code == 404 - r = requests.get(url_get_new, verify=False) + r = session.get(url_get_new) assert r.ok assert json.loads(r.content) == new_tag url_put, payload = _build_url_and_payload('PUT', tag, new_tag) - r = requests.put(url_put, data=payload, verify=False) + r = session.put(url_put, data=payload) assert r.status_code == 404 - r = requests.get(url_get_other, verify=False) + r = session.get(url_get_other, verify=False) assert r.status_code == 404 url_put, payload = _build_url_and_payload('PUT', tag, other_tag) - r = requests.put(url_put, data=payload, verify=False) + r = session.put(url_put, data=payload) assert r.ok - r = requests.get(url_get_other, verify=False) + r = session.get(url_get_other) assert r.ok assert json.loads(r.content) == other_tag - r = requests.get(url_get_tag, verify=False) + r = session.get(url_get_tag) assert r.status_code == 404 - r = requests.delete(url_get_other, verify=False) # url for 'DELETE' is the same as the one for 'GET' + r = session.delete(url_get_other) # url for 'DELETE' is the same as the one for 'GET' assert r.ok - r = requests.get(url_get_other, verify=False) + r = session.get(url_get_other) assert r.status_code == 404 - r = requests.delete(url_get_new, verify=False) # url for 'DELETE' is the same as the one for 'GET' + r = session.delete(url_get_new) # url for 'DELETE' is the same as the one for 'GET' assert r.ok - r = requests.get(url_get_new, verify=False) + r = session.get(url_get_new) assert r.status_code == 404 diff --git a/test/integration_tests/test_users.py b/test/integration_tests/test_users.py index 57b30b061..d5f4e541d 100644 --- a/test/integration_tests/test_users.py +++ b/test/integration_tests/test_users.py @@ -7,13 +7,13 @@ requests.packages.urllib3.disable_warnings() -base_url = 'https://localhost:8443/api' +base_url = 'http://localhost:8080/api' def test_users(): _id = 'new@user.com' - r = requests.get(base_url + '/users/self?user=admin@user.com', verify=False) + r = requests.get(base_url + '/users/self?user=test@user.com') assert r.ok - r = requests.get(base_url + '/users/' + _id + '?user=admin@user.com&root=true', verify=False) + r = requests.get(base_url + '/users/' + _id + '?user=test@user.com&root=true') assert r.status_code == 404 payload = { '_id': _id, @@ -21,15 +21,15 @@ def test_users(): 'lastname': 'User', } payload = json.dumps(payload) - r = requests.post(base_url + '/users?user=admin@user.com&root=true', data=payload, verify=False) + r = requests.post(base_url + '/users?user=test@user.com&root=true', data=payload) assert r.ok - r = requests.get(base_url + '/users/' + _id + '?user=admin@user.com&root=true', verify=False) + r = requests.get(base_url + '/users/' + _id + '?user=test@user.com&root=true') assert r.ok payload = { 'firstname': 'Realname' } payload = json.dumps(payload) - r = requests.put(base_url + '/users/' + _id + '?user=admin@user.com&root=true', data=payload, verify=False) + r = requests.put(base_url + '/users/' + _id + '?user=test@user.com&root=true', data=payload) assert r.ok - r = requests.delete(base_url + '/users/' + _id + '?user=admin@user.com&root=true', verify=False) + r = requests.delete(base_url + '/users/' + _id + '?user=test@user.com&root=true') assert r.ok From ff409e32e30e503d7f5475f12e81bdce0d4f0577 Mon Sep 17 00:00:00 2001 From: Joe Schneider Date: Tue, 9 Feb 2016 13:18:50 -0600 Subject: [PATCH 2/8] Update run.sh to support daemonization for CI testing --- .travis.yml | 17 ++++++++++++++--- bin/runtests.sh | 11 +++++++++-- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index f5f7406b3..ac0681d61 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,21 @@ -language: python +#See https://github.com/travis-ci/travis-ci/issues/2312 for info on why we need +# to install python manually +# Python isn't supported OOTB, so pick a language that makes Travis happy +language: objective-c +os: osx sudo: false -python: -- '2.7' +env: + - SCITRAN_RUNTIME_BOOTSTRAP=test/test_bootstrap.json install: + - brew update + - brew install python +before_script: - bin/install.sh --ci + - bin/run.sh -d script: - bin/runtests.sh unit --ci + - bin/runtests.sh integration --ci after_success: - coveralls +after_script: + - bin/run.sh -s diff --git a/bin/runtests.sh b/bin/runtests.sh index 6dc31dede..23df6f20e 100755 --- a/bin/runtests.sh +++ b/bin/runtests.sh @@ -1,6 +1,7 @@ #!/bin/bash unit_test_path=test/unit_tests/ +integration_test_path=test/integration_tests/ code_path=api/ cd "$( dirname "${BASH_SOURCE[0]}" )/.." @@ -16,8 +17,14 @@ case "$1-$2" in unit---watch) PYTHONPATH=. ptw $unit_test_path $code_path --poll -- $unit_test_path ;; - integration-|integration---ci|integration---watch) - echo "Not implemented yet" + integration---ci) + PYTHONPATH=. py.test $integration_test_path + ;; + integration-) + PYTHONPATH=. py.test $integration_test_path + ;; + integration---watch) + echo "Not implemented" ;; *) echo "Usage: $0 unit|integration [--ci|--watch]" From dadc0c7b860789f1ff5d248c14d65f1f58e37fe1 Mon Sep 17 00:00:00 2001 From: Joe Schneider Date: Thu, 18 Feb 2016 15:49:08 -0600 Subject: [PATCH 3/8] WIP on integration tests in Docker --- bin/runtests.sh | 39 +++- test/Dockerfile | 12 ++ test/docker-compose.yml | 28 +++ test/integration_tests/conftest.py | 152 ++++++++++++++ test/integration_tests/test_collection.py | 172 +++++++--------- test/integration_tests/test_containers.py | 225 +++++++-------------- test/integration_tests/test_download.py | 163 ++++++--------- test/integration_tests/test_errors.py | 31 +-- test/integration_tests/test_groups.py | 43 ++-- test/integration_tests/test_notes.py | 94 +++------ test/integration_tests/test_permissions.py | 133 +++++------- test/integration_tests/test_roles.py | 168 +++++++-------- test/integration_tests/test_tags.py | 112 ++++------ test/integration_tests/test_users.py | 39 ++-- test/requirements-integration-test.txt | 22 ++ 15 files changed, 688 insertions(+), 745 deletions(-) create mode 100644 test/Dockerfile create mode 100644 test/docker-compose.yml create mode 100644 test/integration_tests/conftest.py create mode 100644 test/requirements-integration-test.txt diff --git a/bin/runtests.sh b/bin/runtests.sh index 23df6f20e..fac720f32 100755 --- a/bin/runtests.sh +++ b/bin/runtests.sh @@ -17,11 +17,16 @@ case "$1-$2" in unit---watch) PYTHONPATH=. ptw $unit_test_path $code_path --poll -- $unit_test_path ;; - integration---ci) - PYTHONPATH=. py.test $integration_test_path - ;; - integration-) - PYTHONPATH=. py.test $integration_test_path + integration---ci|integration-) + docker-compose \ + -f test/docker-compose.yml \ + run \ + --rm \ + -e PYTHONPATH=/var/scitran/code/api \ + --entrypoint /var/scitran/code/api/bin/bootstrap.py \ + scitran-core users /var/scitran/test-config/test_bootstrap.json && \ + docker-compose -f test/docker-compose.yml run --rm integration-test + docker-compose -f test/docker-compose.yml down ;; integration---watch) echo "Not implemented" @@ -31,3 +36,27 @@ case "$1-$2" in ;; esac ) + +# +# Coverage not necessary +# Running wsgi container of some kind - use docker/Dockerfile +# Expose on random port - don't care +# Run mongodb container - use open source one with osx workaround... +# Create runtime environment in third container +# Use uwsgi container or use super small python env one? +# Run py.test there, connect to wsgi and mongodb +# How does wsgi container connect to mongodb? +# +# +# +# +# (api/)$ docker build -t scitran-core -f docker/Dockerfile . +# (api/)$ docker run --rm --name test-mongo mongo & +# (api/)$ docker run -e "SCITRAN_PERSISTENT_DB_URI=mongodb://test-mongo:27017/scitran" --link test-mongo --rm -v $(pwd)/test/test_bootstrap.json:/accounts.json scitran-core /var/scitran/code/api/bin/bootstrap.py users /accounts.json +# (api/)$ docker run --rm --name scitran-core -e "SCITRAN_PERSISTENT_DB_URI=mongodb://test-mongo:27017/scitran" -e "SCITRAN_CORE_INSECURE=true" -v $(pwd)/persistent/data:/var/scitran/data -v $(pwd):/var/scitran/code/api --link test-mongo scitran-core uwsgi --ini /var/scitran/config/uwsgi-config.ini --http 0.0.0.0:8080 --python-autoreload 1 & +# (test/)$ docker build -t integration-test . +# (test/integration_tests)$ docker run --link test-mongo --link scitran-core -v $(pwd):/usr/src/tests integration-test test_collection.py +# +# +# get to a prompt +# docker run --link test-mongo --link scitran-core -v $(pwd):/usr/src/tests -it --entrypoint=/bin/bash integration-test diff --git a/test/Dockerfile b/test/Dockerfile new file mode 100644 index 000000000..a58e8f8b6 --- /dev/null +++ b/test/Dockerfile @@ -0,0 +1,12 @@ +FROM python:2.7 + +ENV MONGO_PATH='mongodb://mongo:27017/scitran' +ENV BASE_URL='http://scitran-core:8080/api' + +VOLUME /usr/src/tests +WORKDIR /usr/src/tests + +COPY requirements-integration-test.txt requirements.txt +RUN pip install -r requirements.txt + +ENTRYPOINT ["py.test"] diff --git a/test/docker-compose.yml b/test/docker-compose.yml new file mode 100644 index 000000000..1b16758e5 --- /dev/null +++ b/test/docker-compose.yml @@ -0,0 +1,28 @@ +version: '2' +services: + scitran-core: + build: + context: .. + dockerfile: docker/Dockerfile + links: + - mongo + environment: + - SCITRAN_PERSISTENT_DB_URI=mongodb://mongo:27017/scitran + - SCITRAN_CORE_INSECURE=true + - SCITRAN_CORE_LOG_LEVEL=debug + volumes: + - .:/var/scitran/test-config + - ..:/var/scitran/code/api/ + mongo: + image: mongo + integration-test: + build: + context: ../test + dockerfile: Dockerfile + environment: + - MONGO_PATH=mongodb://mongo:27017/scitran + links: + - scitran-core + - mongo + volumes: + - ./integration_tests:/usr/src/tests diff --git a/test/integration_tests/conftest.py b/test/integration_tests/conftest.py new file mode 100644 index 000000000..c17bb6569 --- /dev/null +++ b/test/integration_tests/conftest.py @@ -0,0 +1,152 @@ +import os +import time +import json +import pytest +import pymongo +import requests + + +@pytest.fixture(scope="session") +def bunch(): + class BunchFactory: + def create(): + return type('Bunch', (), {}) + create = staticmethod(create) + + return BunchFactory() + + +@pytest.fixture(scope="module") +def db(): + mongo_path = os.environ.get('MONGO_PATH', 'mongodb://localhost:9001/scitran') + return pymongo.MongoClient(mongo_path).get_default_database() + + +@pytest.fixture(scope="module") +def base_url(): + return os.environ.get('BASE_URL', 'http://localhost:8080/api') + + +class RequestsAccessor(object): + def __init__(self, base_url, default_params): + self.base_url = base_url + self.default_params = default_params + + def _get_params(self, **kwargs): + params = self.default_params.copy() + if ("params" in kwargs): + params.update(kwargs["params"]) + return params + + def post(self, url_path, *args, **kwargs): + kwargs['params'] = self._get_params(**kwargs) + return requests.post(self.base_url + url_path, verify=False, *args, **kwargs) + + def delete(self, url_path, *args, **kwargs): + kwargs['params'] = self._get_params(**kwargs) + return requests.delete(self.base_url + url_path, verify=False, *args, **kwargs) + + def get(self, url_path, *args, **kwargs): + kwargs['params'] = self._get_params(**kwargs) + return requests.get(self.base_url + url_path, verify=False, *args, **kwargs) + + def put(self, url_path, *args, **kwargs): + kwargs['params'] = self._get_params(**kwargs) + return requests.put(self.base_url + url_path, verify=False, *args, **kwargs) + + +@pytest.fixture(scope="module") +def api_as_admin(base_url): + accessor = RequestsAccessor(base_url, {"user": "admin@user.com", "root": "true"}) + return accessor + + +@pytest.fixture(scope="module") +def api_as_user(base_url): + accessor = RequestsAccessor(base_url, {"user": "admin@user.com"}) + return accessor + + +@pytest.fixture(scope="module") +def api_accessor(base_url): + class RequestsAccessorWithBaseUrl(RequestsAccessor): + def __init__(self, user): + super(self.__class__, self).__init__(base_url, {"user": user}) + + return RequestsAccessorWithBaseUrl + + +@pytest.fixture() +def with_a_group_and_a_project(api_as_admin, data_builder, request, bunch): + + user_1 = 'user1@user.com' + user_2 = 'user2@user.com' + + group_id = 'test_group_' + str(int(time.time() * 1000)) + data_builder.create_group(group_id) + project_id = data_builder.create_project(group_id) + + def teardown_db(): + data_builder.delete_project(project_id) + data_builder.delete_group(group_id) + + request.addfinalizer(teardown_db) + + fixture_data = bunch.create() + fixture_data.project_id = project_id + fixture_data.user_1 = user_1 + fixture_data.user_2 = user_2 + return fixture_data + + +@pytest.fixture(scope="module") +def data_builder(api_as_admin): + class DataBuilder: + + # This madness allows us nicer reading code by auto-generating fucntions. + def __getattr__(self, name): + parent_attribute = { + 'group': '_id', + 'project': 'group', + 'session': 'project', + 'acquisition': 'session' + } + + # create_( parent_id ) + # + # Call the functions create_group(), create_project(), create_session(), + # or create_acquisition(), passing in the "parent" container id as the singular + # parameter. + if name.startswith('create_'): + def create_(parent_id): + container = name.split('create_')[1] + parent = parent_attribute[container] + api_path = '/' + container + 's' # API paths are pluralized + + payload = {parent: parent_id} + if (container != 'group'): + payload.update({'public': True, 'label': container + '_testing'}) + payload = json.dumps(payload) + + print api_path, payload + r = api_as_admin.post(api_path, data=payload) + print r.content + + assert r.ok + + return json.loads(r.content)['_id'] + return create_ + + # delete_( id ) + # + # Call the functions delete_group(), delete_project(), delete_session(), + # or delete_acquisition(), passing in the id as the only parameter. + if name.startswith('delete_'): + def delete_(id): + container = name.split('delete_')[1] + api_path = '/' + container + 's' # API paths are pluralized + r = api_as_admin.delete(api_path + '/' + id) + assert r.ok + + return delete_ + return DataBuilder() diff --git a/test/integration_tests/test_collection.py b/test/integration_tests/test_collection.py index 1a44b83a5..c5c83d901 100644 --- a/test/integration_tests/test_collection.py +++ b/test/integration_tests/test_collection.py @@ -1,118 +1,92 @@ -import requests import json -import time import logging +import pytest log = logging.getLogger(__name__) sh = logging.StreamHandler() log.addHandler(sh) -log.setLevel(logging.INFO) - -from nose.tools import with_setup -import pymongo -from bson.objectid import ObjectId - -db = pymongo.MongoClient('mongodb://localhost:9001/scitran').get_default_database() -adm_user = 'test@user.com' -base_url = 'http://localhost:8080/api' -test_data = type('',(object,),{})() - -def setup_db(): - global session - session = requests.Session() - session.params = { - 'user': adm_user, - 'root': True - } - test_data.group_id = 'test_group_' + str(int(time.time()*1000)) - payload = { - '_id': test_data.group_id - } - payload = json.dumps(payload) - r = session.post(base_url + '/groups', data=payload) - assert r.ok - payload = { - 'group': test_data.group_id, - 'label': 'test_project', - 'public': False - } - payload = json.dumps(payload) - r = session.post(base_url + '/projects', data=payload) - test_data.pid = json.loads(r.content)['_id'] - assert r.ok - log.debug('pid = \'{}\''.format(test_data.pid)) - - payload = { - 'project': test_data.pid, - 'label': 'session_testing', - 'public': False - } - payload = json.dumps(payload) - r = session.post(base_url + '/sessions', data=payload) - assert r.ok - test_data.sid = json.loads(r.content)['_id'] - log.debug('sid = \'{}\''.format(test_data.sid)) - - payload = { - 'session': test_data.sid, - 'label': 'acq_testing', - 'public': False - } - payload = json.dumps(payload) - r = session.post(base_url + '/acquisitions', data=payload) - assert r.ok - test_data.aid = json.loads(r.content)['_id'] - log.debug('aid = \'{}\''.format(test_data.aid)) -def teardown_db(): - session.params['root'] = True - r = session.delete(base_url + '/acquisitions/' + test_data.aid) - assert r.ok - r = session.delete(base_url + '/sessions/' + test_data.sid) - assert r.ok - r = session.delete(base_url + '/projects/' + test_data.pid) - assert r.ok + +def test_collections(api_as_user, single_project_session_acquisition_tree): + data = single_project_session_acquisition_tree + + my_collection_id = create_collection(api_as_user) + get_collection(api_as_user, my_collection_id) + add_session_to_collection(api_as_user, data.sid, my_collection_id) + + r = api_as_user.get('/acquisitions/' + data.aid) + collections = json.loads(r.content)['collections'] + assert my_collection_id in collections + + delete_collection(api_as_user, my_collection_id) + + r = api_as_user.get('/collections/' + my_collection_id) + assert r.status_code == 404 + + r = api_as_user.get('/acquisitions/' + data.aid) + collections = json.loads(r.content)['collections'] + assert my_collection_id not in collections -@with_setup(setup_db, teardown_db) -def test_collections(): - payload = { - 'curator': adm_user, - 'label': 'test_collection_'+ str(int(time.time())) , - 'public': False - } - session.params['root'] = False - r = session.post(base_url + '/collections', data=json.dumps(payload)) +# This fixture sets up a single project->session->acquisition hierarchy in the db +@pytest.fixture(scope="module") +def single_project_session_acquisition_tree(api_as_admin, request, bunch, data_builder): + + pid = data_builder.create_project('scitran') + sid = data_builder.create_session(pid) + aid = data_builder.create_acquisition(sid) + + def teardown_db(): + data_builder.delete_acquisition(aid) + data_builder.delete_session(sid) + data_builder.delete_project(pid) + + # Setup teardown handler + request.addfinalizer(teardown_db) + + # This sets up a poor man's dot-notation dict + fixture_data = bunch.create() + fixture_data.sid = sid + fixture_data.aid = aid + return fixture_data + + +# Return collection id created +def create_collection(api): + # POST - Create a collection + NEW_COLLECTION_JSON = json.dumps({ + 'curator': 'admin@user.com', + 'label': 'SciTran/Testing', + 'public': True + }) + r = api.post('/collections', data=NEW_COLLECTION_JSON) assert r.ok - _id = json.loads(r.content)['_id'] - log.debug('_id = \'{}\''.format(_id)) - r = session.get(base_url + '/collections/' + _id) + return json.loads(r.content)['_id'] + + +def get_collection(api, collection_id): + # GET - Retrieve a collection + r = api.get('/collections/' + collection_id) assert r.ok - payload = { - 'contents':{ + + +def add_session_to_collection(api, session_id, collection_id): + # PUT - Add session to collection + ADD_SESSION_TO_COLLECTION_JSON = json.dumps({ + 'contents': { 'nodes': [{ 'level': 'session', - '_id': test_data.sid + '_id': session_id, }], 'operation': 'add' } - } - r = session.put(base_url + '/collections/' + _id, data=json.dumps(payload)) - assert r.ok - r = session.get(base_url + '/collections/' + _id + '/acquisitions?session=' + test_data.sid) + }) + r = api.put('/collections/' + collection_id, data=ADD_SESSION_TO_COLLECTION_JSON) assert r.ok - coll_acq_id= json.loads(r.content)[0]['_id'] - assert coll_acq_id == test_data.aid - acq_ids = [ObjectId(test_data.aid)] - acs = db.acquisitions.find({'_id': {'$in': acq_ids}}) - for ac in acs: - assert len(ac['collections']) == 1 - assert ac['collections'][0] == ObjectId(_id) - r = session.delete(base_url + '/collections/' + _id) + + +def delete_collection(api, collection_id): + # DELETE - Delete the collection + r = api.delete('/collections/' + collection_id) assert r.ok - r = session.get(base_url + '/collections/' + _id) - assert r.status_code == 404 - acs = db.acquisitions.find({'_id': {'$in': acq_ids}}) - for ac in acs: - assert len(ac['collections']) == 0 diff --git a/test/integration_tests/test_containers.py b/test/integration_tests/test_containers.py index cdfdec9e2..652a90225 100644 --- a/test/integration_tests/test_containers.py +++ b/test/integration_tests/test_containers.py @@ -1,174 +1,87 @@ -import requests import json import time -from nose.tools import with_setup import logging +import pytest log = logging.getLogger(__name__) sh = logging.StreamHandler() log.addHandler(sh) -base_url = 'http://localhost:8080/api' -adm_user = 'test@user.com' -test_data = type('',(object,),{})() - -def setup_db(): - global session - session = requests.Session() - # all the requests will be performed as root - session.params = { - 'user': adm_user, - 'root': True - } - - # Create a group - test_data.group_id = 'test_group_' + str(int(time.time()*1000)) - payload = { - '_id': test_data.group_id - } - payload = json.dumps(payload) - r = session.post(base_url + '/groups', data=payload) - assert r.ok - test_data.group_id_1 = 'test_group_' + str(int(time.time()*1000)) - payload = { - '_id': test_data.group_id_1 - } - payload = json.dumps(payload) - r = session.post(base_url + '/groups', data=payload) - assert r.ok -def teardown_db(): - r = session.delete(base_url + '/groups/' + test_data.group_id) - assert r.ok - r = session.delete(base_url + '/groups/' + test_data.group_id_1) - assert r.ok +@pytest.fixture(scope="module") +def with_two_groups(api_as_admin, bunch, request, data_builder): + group_1 = data_builder.create_group('test_group_' + str(int(time.time() * 1000))) + group_2 = data_builder.create_group('test_group_' + str(int(time.time() * 1000))) -@with_setup(setup_db, teardown_db) -def test_projects(): - payload = { - 'group': test_data.group_id, - 'label': 'test_project', - 'public': False - } - payload = json.dumps(payload) - r = session.post(base_url + '/projects', data=payload) - assert r.ok - _id = json.loads(r.content)['_id'] - r = session.get(base_url + '/projects/' + _id) - assert r.ok - payload = { - 'group': test_data.group_id_1, - } - payload = json.dumps(payload) - r = session.put(base_url + '/projects/' + _id, data=payload) - assert r.ok - r = session.delete(base_url + '/projects/' + _id) - assert r.ok + def teardown_db(): + data_builder.delete_group(group_1) + data_builder.delete_group(group_2) -@with_setup(setup_db, teardown_db) -def test_sessions(): - payload = { - 'group': test_data.group_id, - 'label': 'test_project', - 'public': False - } - payload = json.dumps(payload) - r = session.post(base_url + '/projects', data=payload) - assert r.ok - pid = json.loads(r.content)['_id'] - payload = { - 'project': pid, - 'label': 'session_testing', - 'public': False - } - payload = json.dumps(payload) - r = session.post(base_url + '/sessions', data=payload) - assert r.ok - _id = json.loads(r.content)['_id'] - r = session.get(base_url + '/sessions/' + _id) - assert r.ok - payload = { - 'group': test_data.group_id, - 'label': 'test_project_1', - 'public': False - } - payload = json.dumps(payload) - r = session.post(base_url + '/projects', data=payload) - new_pid = json.loads(r.content)['_id'] - assert r.ok - payload = { - 'project': new_pid, - } - payload = json.dumps(payload) - r = session.put(base_url + '/sessions/' + _id, data=payload) - assert r.ok - r = session.delete(base_url + '/sessions/' + _id) - assert r.ok - r = session.get(base_url + '/sessions/' + _id) - assert r.status_code == 404 - r = session.delete(base_url + '/projects/' + pid) - assert r.ok - r = session.delete(base_url + '/projects/' + new_pid) - assert r.ok + request.addfinalizer(teardown_db) -@with_setup(setup_db, teardown_db) -def test_acquisitions(): - payload = { - 'group': test_data.group_id, - 'label': 'test_project', - 'public': False - } - payload = json.dumps(payload) - r = session.post(base_url + '/projects', data=payload) - assert r.ok - pid = json.loads(r.content)['_id'] - payload = { - 'project': pid, - 'label': 'session_testing', - 'public': False - } - payload = json.dumps(payload) - r = session.post(base_url + '/sessions', data=payload) - assert r.ok - sid = json.loads(r.content)['_id'] - - payload = { - 'project': pid, - 'label': 'session_testing_1', - 'public': False - } - payload = json.dumps(payload) - r = session.post(base_url + '/sessions', data=payload) - assert r.ok - new_sid = json.loads(r.content)['_id'] - - payload = { - 'session': sid, - 'label': 'acq_testing', - 'public': False - } - payload = json.dumps(payload) - r = session.post(base_url + '/acquisitions', data=payload) - assert r.ok - aid = json.loads(r.content)['_id'] + fixture_data = bunch.create() + fixture_data.group_1 = group_1 + fixture_data.group_2 = group_2 + return fixture_data - r = session.get(base_url + '/acquisitions/' + aid) - assert r.ok - payload = { - 'session': new_sid - } - payload = json.dumps(payload) - r = session.put(base_url + '/acquisitions/' + aid, data=payload) - assert r.ok +# Create project +# Add it to a group +# Switch the project to the second group +# Delete the project +def test_switching_project_between_groups(with_two_groups, data_builder, api_as_user): + data = with_two_groups - r = session.delete(base_url + '/acquisitions/' + aid) - assert r.ok - r = session.get(base_url + '/acquisitions/' + aid) - assert r.status_code == 404 - r = session.delete(base_url + '/sessions/' + sid) + pid = data_builder.create_project(data.group_1) + assert api_as_user.get('/projects/' + pid).ok + r = api_as_user.get('/groups/' + data.group_1 + '/projects') + print json.loads(r.content) + + payload = json.dumps({'group': with_two_groups.group_2}) + r = api_as_user.put('/projects/' + pid, data=payload) assert r.ok - r = session.delete(base_url + '/sessions/' + new_sid) + + r = api_as_user.get('/projects/' + pid) + assert r.ok and json.loads(r.content)['group'] == data.group_2 + + data_builder.delete_project(pid) + + +def test_switching_session_between_projects(with_two_groups, data_builder, api_as_user): + data = with_two_groups + + project_1_id = data_builder.create_project(data.group_1) + project_2_id = data_builder.create_project(data.group_1) + session_id = data_builder.create_session(project_1_id) + + payload = json.dumps({'project': project_2_id}) + r = api_as_user.put('/sessions/' + session_id, data=payload) assert r.ok - r = session.delete(base_url + '/projects/' + pid) + + r = api_as_user.get('/sessions/' + session_id) + assert r.ok and json.loads(r.content)['project'] == project_2_id + + data_builder.delete_session(session_id) + data_builder.delete_project(project_1_id) + data_builder.delete_project(project_2_id) + + +def test_switching_acquisition_between_projects(with_two_groups, data_builder, api_as_user): + data = with_two_groups + + project_id = data_builder.create_project(data.group_1) + session_1_id = data_builder.create_session(project_id) + session_2_id = data_builder.create_session(project_id) + acquisition_id = data_builder.create_acquisition(session_1_id) + + payload = json.dumps({'session': session_2_id}) + r = api_as_user.put('/acquisitions/' + acquisition_id, data=payload) assert r.ok + + r = api_as_user.get('/acquisitions/' + acquisition_id) + assert r.ok and json.loads(r.content)['session'] == session_2_id + + data_builder.delete_acquisition(acquisition_id) + data_builder.delete_session(session_1_id) + data_builder.delete_session(session_2_id) + data_builder.delete_project(project_id) diff --git a/test/integration_tests/test_download.py b/test/integration_tests/test_download.py index 4f6c49307..0cecc0762 100644 --- a/test/integration_tests/test_download.py +++ b/test/integration_tests/test_download.py @@ -1,137 +1,90 @@ -import requests +import os import json import time +import pytest import logging -from nose.tools import with_setup +import tarfile +import cStringIO log = logging.getLogger(__name__) sh = logging.StreamHandler() log.addHandler(sh) -log.setLevel(logging.INFO) -base_url = 'http://localhost:8080/api' -test_data = type('',(object,),{})() +@pytest.fixture() +def with_a_download_available(api_as_admin, data_builder, bunch, request): + file_name = "test.csv" + group_id = 'test_group_' + str(int(time.time() * 1000)) -session = None + data_builder.create_group(group_id) + project_id = data_builder.create_project(group_id) + session_id = data_builder.create_session(project_id) + acquisition_id = data_builder.create_acquisition(session_id) -def setup_download(): - global session - session = requests.Session() - # all the requests will be performed as root - session.params = { - 'user': 'test@user.com', - 'root': True - } - - # Create a group - test_data.group_id = 'test_group_' + str(int(time.time()*1000)) - payload = { - '_id': test_data.group_id - } - payload = json.dumps(payload) - r = session.post(base_url + '/groups', data=payload) - assert r.ok - - # Create a project - payload = { - 'group': test_data.group_id, - 'label': 'scitran_testing', - 'public': False - } - payload = json.dumps(payload) - r = session.post(base_url + '/projects', data=payload) - test_data.pid = json.loads(r.content)['_id'] - assert r.ok - log.debug('pid = \'{}\''.format(test_data.pid)) - - # Create a session - payload = { - 'project': test_data.pid, - 'label': 'session_testing', - 'public': False - } - payload = json.dumps(payload) - r = session.post(base_url + '/sessions', data=payload) - assert r.ok - test_data.sid = json.loads(r.content)['_id'] - log.debug('sid = \'{}\''.format(test_data.sid)) - - # Create an acquisition - payload = { - 'session': test_data.sid, - 'label': 'acq_testing', - 'public': False - } - payload = json.dumps(payload) - r = session.post(base_url + '/acquisitions', data=payload) - assert r.ok - test_data.aid = json.loads(r.content)['_id'] - log.debug('aid = \'{}\''.format(test_data.aid)) - - ## multiform fields for the file upload - files = {'file': ('test.csv', 'some,data,to,send\nanother,row,to,send\n'), + # multiform fields for the file upload + files = {'file': (file_name, 'some,data,to,send\nanother,row,to,send\n'), 'tags': ('', '["incomplete"]'), - 'metadata': ('', - '{"group": {"_id": "scitran"}, ' \ - '"project": {"label": "Testdata"}, ' \ - '"session": {"uid": "1.2.840.113619.6.353.10437158128305161617400354036593525848"}, ' \ - '"file": {"type": "nifti"}, ' - '"acquisition": {"uid": "1.2.840.113619.2.353.4120.7575399.14591.1403393566.658_1", ' \ - '"timestamp": "1970-01-01T00:00:00", ' \ - '"label": "Screen Save", ' \ - '"instrument": "MRI", ' \ - '"measurement": "screensave", ' \ - '"timezone": "America/Los_Angeles"}, ' \ - '"subject": {"code": "ex7236"}}' - )} + 'metadata': + ('', + '''{ "group": {"_id": "scitran"}, + "project": {"label": "Testdata"}, + "session": {"uid": "1.2.840.113619.6.353.10437158128305161617400354036593525848"}, + "file": {"type": "nifti"}, + "acquisition": {"uid": "1.2.840.113619.2.353.4120.7575399.14591.1403393566.658_1", + "timestamp": "1970-01-01T00:00:00", + "label": "Screen Save", + "instrument": "MRI", + "measurement": "screensave", + "timezone": "America/Los_Angeles"}, + "subject": {"code": "ex7236"} + }''' + ) + } # upload the same file to each container created in the test - session.post(base_url + '/acquisitions/' + test_data.aid +'/files', files=files) - session.post(base_url + '/sessions/' + test_data.sid +'/files', files=files) - session.post(base_url + '/projects/' + test_data.pid +'/files', files=files) + api_as_admin.post('/acquisitions/' + acquisition_id + '/files', files=files) + api_as_admin.post('/sessions/' + session_id + '/files', files=files) + api_as_admin.post('/projects/' + project_id + '/files', files=files) + + def teardown_download(): + api_as_admin.delete('/acquisitions/' + acquisition_id) + api_as_admin.delete('/sessions/' + session_id) + api_as_admin.delete('/projects/' + project_id) + api_as_admin.delete('/groups/' + group_id) + + request.addfinalizer(teardown_download) + fixture_data = bunch.create() + fixture_data.project_id = project_id + fixture_data.file_name = file_name + return fixture_data -def teardown_download(): - success = True - # remove all the container created in the test - r = session.delete(base_url + '/acquisitions/' + test_data.aid) - success = success and r.ok - r = session.delete(base_url + '/sessions/' + test_data.sid) - success = success and r.ok - r = session.delete(base_url + '/projects/' + test_data.pid) - success = success and r.ok - r = session.delete(base_url + '/groups/' + test_data.group_id) - success = success and r.ok - session.close() - if not success: - log.error('error in the teardown. These containers may have not been removed.') - log.error(str(test_data.__dict__)) +def test_download(with_a_download_available, api_as_admin): + data = with_a_download_available -@with_setup(setup_download, teardown_download) -def test_download(): # Retrieve a ticket for a batch download - payload = { + payload = json.dumps({ 'optional': False, 'nodes': [ { 'level': 'project', - '_id': test_data.pid + '_id': data.project_id } ] - } - payload = json.dumps(payload) - r = session.post(base_url + '/download', data=payload) + }) + r = api_as_admin.post('/download', data=payload) assert r.ok # Perform the download ticket = json.loads(r.content)['ticket'] - r = session.get(base_url + '/download', params={'ticket': ticket}) + r = api_as_admin.get('/download', params={'ticket': ticket}) assert r.ok - # Save the tar to a file if successful - f = open('test_download.tar', 'w') - f.write(r.content) - f.close() + tar_file = cStringIO.StringIO(r.content) + tar = tarfile.open(mode="r", fileobj=tar_file) + # Verify a single file in tar with correct file name + for tarinfo in tar: + assert os.path.basename(tarinfo.name) == data.file_name + tar.close() diff --git a/test/integration_tests/test_errors.py b/test/integration_tests/test_errors.py index 01cdffe06..df8dd3cce 100644 --- a/test/integration_tests/test_errors.py +++ b/test/integration_tests/test_errors.py @@ -1,26 +1,27 @@ -import requests import json +import time import logging + log = logging.getLogger(__name__) sh = logging.StreamHandler() log.addHandler(sh) -import warnings -warnings.filterwarnings('ignore') -base_url = 'http://localhost:8080/api' -import pymongo -db = pymongo.MongoClient('mongodb://localhost:9001/scitran').get_default_database() -projects = db.projects -def test_extra_param(): - payload = { +def test_extra_param(api_as_admin): + label = 'SciTran/testing_' + str(int(time.time() * 1000)) + + bad_payload = json.dumps({ 'group': 'unknown', - 'label': 'SciTran/Testing', + 'label': label, 'public': False, 'extra_param': 'some_value' - } - payload = json.dumps(payload) - r = requests.post(base_url + '/projects?user=test@user.com&root=true', data=payload) + }) + + r = api_as_admin.post('/projects', data=bad_payload) assert r.status_code == 400 - r = projects.delete_many({'label': 'SciTran/Testing'}) - assert r.deleted_count == 0 + + r = api_as_admin.get('/projects') + assert r.ok + projects = json.loads(r.content) + filtered_projects = filter(lambda e: e['label'] == label, projects) + assert len(filtered_projects) == 0 diff --git a/test/integration_tests/test_groups.py b/test/integration_tests/test_groups.py index 75b204b7e..0db3b74f6 100644 --- a/test/integration_tests/test_groups.py +++ b/test/integration_tests/test_groups.py @@ -2,35 +2,28 @@ import json import time import logging + log = logging.getLogger(__name__) sh = logging.StreamHandler() log.addHandler(sh) -base_url = 'http://localhost:8080/api' - -def test_groups(): - session = requests.Session() - # all the requests will be performed as root - session.params = { - 'user': 'test@user.com', - 'root': True - } - _id = 'test_group_' + str(int(time.time()*1000)) - r = session.get(base_url + '/groups/' + _id) + +def test_groups(api_as_admin, data_builder): + group_id = 'test_group_' + str(int(time.time() * 1000)) + + # Cannot find a non-existant group + r = api_as_admin.get('/groups/' + group_id) assert r.status_code == 404 - payload = { - '_id': _id - } - payload = json.dumps(payload) - r = session.post(base_url + '/groups', data=payload) - assert r.ok - r = session.get(base_url + '/groups/' + _id) - assert r.ok - payload = { - 'name': 'Test group', - } - payload = json.dumps(payload) - r = session.put(base_url + '/groups/' + _id, data=payload) + + data_builder.create_group(group_id) + + # Able to find new group + r = api_as_admin.get('/groups/' + group_id) assert r.ok - r = session.delete(base_url + '/groups/' + _id) + + # Able to change group name + payload = json.dumps({'name': 'Test group'}) + r = api_as_admin.put('/groups/' + group_id, data=payload) assert r.ok + + data_builder.delete_group(group_id) diff --git a/test/integration_tests/test_notes.py b/test/integration_tests/test_notes.py index 4ab669d92..7a3e8acb0 100644 --- a/test/integration_tests/test_notes.py +++ b/test/integration_tests/test_notes.py @@ -1,85 +1,45 @@ -import requests import json import time -from nose.tools import with_setup +import pytest import logging log = logging.getLogger(__name__) sh = logging.StreamHandler() log.addHandler(sh) -log.setLevel(logging.INFO) -adm_user = 'test@user.com' -test_data = type('',(object,),{})() -base_url = 'http://localhost:8080/api' -def _build_url(_id=None, requestor=adm_user): - if _id is None: - url = test_data.proj_url + '?user=' + requestor - else: - url = test_data.proj_url + '/' + _id + '?user=' + requestor - return url +def test_notes(with_a_group_and_a_project, api_as_user): + data = with_a_group_and_a_project + notes_path = '/projects/' + data.project_id + '/notes' -def setup_db(): - global session - session = requests.Session() - # all the requests will be performed as root - session.params = { - 'user': adm_user, - 'root': True - } - - # Create a group - test_data.group_id = 'test_group_' + str(int(time.time()*1000)) - payload = { - '_id': test_data.group_id - } - payload = json.dumps(payload) - r = session.post(base_url + '/groups', data=payload) - assert r.ok - payload = { - 'group': test_data.group_id, - 'label': 'test_project', - 'public': False - } - payload = json.dumps(payload) - r = session.post(base_url + '/projects', data=payload) - test_data.pid = json.loads(r.content)['_id'] + # Add a note + new_note = json.dumps({'text': 'test note'}) + r = api_as_user.post(notes_path, data=new_note) assert r.ok - log.debug('pid = \'{}\''.format(test_data.pid)) - test_data.proj_url = base_url + '/projects/{}/notes'.format(test_data.pid) -def teardown_db(): - r = session.delete(base_url + '/projects/' + test_data.pid) - assert r.ok - r = session.delete(base_url + '/groups/' + test_data.group_id) + # Verify note is present in project + r = api_as_user.get('/projects/' + data.project_id) assert r.ok + project = json.loads(r.content) + assert len(project['notes']) == 1 -@with_setup(setup_db, teardown_db) -def test_notes(): - url_post = test_data.proj_url + note_id = project['notes'][0]['_id'] + note_path = '/projects/' + data.project_id + '/notes/' + note_id + r = api_as_user.get(note_path) + assert r.ok and json.loads(r.content)['_id'] == note_id - data = {'text':'test note'} - r = session.post(url_post, data=json.dumps(data)) - assert r.ok - r = session.get(base_url + '/projects/{}?user={}'.format(test_data.pid, adm_user)) - assert r.ok - p = json.loads(r.content) - assert len(p['notes']) == 1 - assert p['notes'][0]['user'] == adm_user - note_id = p['notes'][0]['_id'] - url_get = test_data.proj_url + '/' + note_id - r = session.get(url_get) - assert r.ok - assert json.loads(r.content)['_id'] == note_id - data = {'text':'modified test note'} - r = session.put(url_get, data=json.dumps(data)) + # Modify note + modified_note = json.dumps({'text': 'modified test note'}) + r = api_as_user.put(note_path, data=modified_note) assert r.ok - r = session.get(url_get) - assert r.ok - assert json.loads(r.content)['text'] == 'modified test note' - r = session.delete(url_get) + + # Verify modified note + r = api_as_user.get(note_path) + assert r.ok and json.loads(r.content)['text'] == 'modified test note' + + # Delete note + r = api_as_user.delete(note_path) assert r.ok - r = session.get(url_get) - assert r.status_code == 404 + r = api_as_user.get(note_path) + assert r.status_code == 404 diff --git a/test/integration_tests/test_permissions.py b/test/integration_tests/test_permissions.py index 8ba38f4e8..190946ac2 100644 --- a/test/integration_tests/test_permissions.py +++ b/test/integration_tests/test_permissions.py @@ -1,114 +1,83 @@ -import requests import json import time -from nose.tools import with_setup +import pytest import logging log = logging.getLogger(__name__) sh = logging.StreamHandler() log.addHandler(sh) -log.setLevel(logging.INFO) -adm_user = 'test@user.com' -user = 'other@user.com' -user1 = 'other1@user.com' -test_data = type('',(object,),{})() -base_url = 'http://localhost:8080/api' -session = None -def _build_url(_id=None, requestor=adm_user, site='local'): - if _id is None: - url = test_data.proj_url + '?user=' + requestor - else: - url = test_data.proj_url + '/' + site + '/' + _id + '?user=' + requestor - return url +def test_permissions(with_a_group_and_a_project, api_as_admin): + data = with_a_group_and_a_project + permissions_path = '/projects/' + data.project_id + '/permissions' + user_1_local_path = permissions_path + '/local/' + data.user_1 + user_2_local_path = permissions_path + '/local/' + data.user_2 + user_2_another_path = permissions_path + '/another/' + data.user_2 + # GET is not allowed for general permissions path + r = api_as_admin.get(permissions_path) + assert r.status_code == 405 -def setup_db(): - global session - session = requests.Session() - # all the requests will be performed as root - session.params = { - 'user': adm_user, - 'root': True - } - - # Create a group - test_data.group_id = 'test_group_' + str(int(time.time()*1000)) - payload = { - '_id': test_data.group_id - } - payload = json.dumps(payload) - r = session.post(base_url + '/groups', data=payload) - assert r.ok - payload = { - 'group': test_data.group_id, - 'label': 'test_project', - 'public': False - } - payload = json.dumps(payload) - r = session.post(base_url + '/projects', data=payload) - test_data.pid = json.loads(r.content)['_id'] - assert r.ok - log.debug('pid = \'{}\''.format(test_data.pid)) - test_data.proj_url = base_url + '/projects/{}/permissions'.format(test_data.pid) - -def teardown_db(): - r = session.delete(base_url + '/projects/' + test_data.pid) - assert r.ok - r = session.delete(base_url + '/groups/' + test_data.group_id) - assert r.ok - -@with_setup(setup_db, teardown_db) -def test_permissions(): - url_post = _build_url() - url_get = _build_url(user) - url_get_1 = _build_url(user1) - r = requests.get(url_get) - assert r.status_code == 404 - data = { - '_id': user, + # Add permissions for user 1 + payload = json.dumps({ + '_id': data.user_1, 'site': 'local', 'access': 'ro' - } - r = requests.post(url_post, data = json.dumps(data)) + }) + r = api_as_admin.post(permissions_path, data=payload) assert r.ok - r = requests.get(url_get) + + # Verify permissions for user 1 + r = api_as_admin.get(user_1_local_path) assert r.ok content = json.loads(r.content) - assert content['_id'] == user + assert content['_id'] == data.user_1 assert content['site'] == 'local' assert content['access'] == 'ro' - data = { + + # Update user 1 to have admin access + payload = json.dumps({ 'access': 'admin' - } - r = requests.put(url_get, data = json.dumps(data)) + }) + r = api_as_admin.put(user_1_local_path, data=payload) assert r.ok - data = { - '_id': user1, + + # Add user 2 to have ro access + payload = json.dumps({ + '_id': data.user_2, 'site': 'local', 'access': 'ro' - } - r = requests.post(url_post, data = json.dumps(data)) + }) + r = api_as_admin.post(permissions_path, data=payload) assert r.ok - data = { - '_id': user - } - r = requests.put(url_get_1, data = json.dumps(data)) + + # Attempt to change user 2's id to user 1 + payload = json.dumps({ + '_id': data.user_1 + }) + r = api_as_admin.put(user_2_local_path, data=payload) assert r.status_code == 404 - data = { + + # Change user 2's site + payload = json.dumps({ 'site': 'another' - } - r = requests.put(url_get_1, data = json.dumps(data)) + }) + r = api_as_admin.put(user_2_local_path, data=payload) assert r.ok - url_get_1 = _build_url(user1, site='another') - r = requests.get(url_get_1) + + # Verify user 2's site changed + r = api_as_admin.get(user_2_another_path) assert r.ok content = json.loads(r.content) - assert content['_id'] == user1 + assert content['_id'] == data.user_2 assert content['site'] == 'another' assert content['access'] == 'ro' - r = requests.delete(url_get_1) + + # Delete user 2 + r = api_as_admin.delete(user_2_another_path) assert r.ok - r = requests.get(url_get_1) + + # Ensure user 2 is gone + r = api_as_admin.get(user_2_another_path) assert r.status_code == 404 diff --git a/test/integration_tests/test_roles.py b/test/integration_tests/test_roles.py index 1c45a859a..e6dc78dc9 100644 --- a/test/integration_tests/test_roles.py +++ b/test/integration_tests/test_roles.py @@ -1,114 +1,92 @@ -import requests -import os import json import time -from nose.tools import with_setup - -base_url = 'http://localhost:8080/api' -adm_user = 'test@user.com' -user = 'other@user.com' -test_data = type('',(object,),{})() - - -def setup_db(): - global session - session = requests.Session() - # all the requests will be performed as root - session.params = { - 'user': adm_user, - 'root': True - } - - # Create a group - test_data.group_id = 'test_group_' + str(int(time.time()*1000)) - payload = { - '_id': test_data.group_id - } - payload = json.dumps(payload) - r = session.post(base_url + '/groups', data=payload) - assert r.ok - payload = { - '_id': user, +import pytest + + +@pytest.fixture() +def with_a_group_and_a_user(data_builder, api_as_admin, request, bunch): + user_id = 'other@user.com' + group_id = 'test_group_' + str(int(time.time() * 1000)) + data_builder.create_group(group_id) + + payload = json.dumps({ + '_id': user_id, 'firstname': 'Other', 'lastname': 'User', - } - payload = json.dumps(payload) - r = session.post(base_url + '/users', data=payload) - assert r.ok - session.params = {} - -def teardown_db(): - session.params = { - 'user': adm_user, - 'root': True - } - r = session.delete(base_url + '/groups/' + test_data.group_id) - assert r.ok - r = session.delete(base_url + '/users/' + user) + }) + r = api_as_admin.post('/users', data=payload) assert r.ok -def _build_url_and_payload(method, user, access, site='local'): - - url = os.path.join(base_url, 'groups', test_data.group_id, 'roles') - if method == 'POST': - payload = { - '_id': user, - 'site': site, - 'access': access - } - return url, json.dumps(payload) - else: - return os.path.join(url, site, user), None - -@with_setup(setup_db, teardown_db) -def test_roles(): - session.params = { - 'user': adm_user - } - url_get, _ = _build_url_and_payload('GET', user, None) - r = session.get(url_get) + def teardown_db(): + data_builder.delete_group(group_id) + api_as_admin.delete('/users/' + user_id) + + request.addfinalizer(teardown_db) + + fixture_data = bunch.create() + fixture_data.user_id = user_id + fixture_data.group_id = group_id + return fixture_data + + +def create_role_payload(user, site, access): + return json.dumps({ + '_id': user, + 'site': site, + 'access': access + }) + + +def test_roles(api_as_admin, with_a_group_and_a_user, api_accessor): + data = with_a_group_and_a_user + api_as_other_user = api_accessor(data.user_id) + + roles_path = '/groups/' + data.group_id + '/roles' + local_user_roles_path = roles_path + '/local/' + data.user_id + admin_user_roles_path = roles_path + '/local/' + 'admin@user.com' + + # Cannot retrieve roles that don't exist + r = api_as_admin.get(local_user_roles_path) assert r.status_code == 404 - url_post, payload = _build_url_and_payload('POST', user, 'rw') - r = session.post(url_post, data=payload) + # Create role for user + payload = create_role_payload(data.user_id, 'local', 'rw') + r = api_as_admin.post(roles_path, data=payload) assert r.ok - r = session.get(url_get) + + # Verify new user role + r = api_as_admin.get(local_user_roles_path) assert r.ok content = json.loads(r.content) assert content['access'] == 'rw' - assert content['_id'] == user - session.params = { - 'user': user - } - url_get_not_auth, _ = _build_url_and_payload('GET', adm_user, None) - r = session.get(url_get_not_auth) + assert content['_id'] == data.user_id + + # 'rw' users cannot access other user roles + r = api_as_other_user.get(admin_user_roles_path) assert r.status_code == 403 - session.params = { - 'user': adm_user - } - payload = json.dumps({'access':'admin'}) - r = session.put(url_get, data=payload) + + # Upgrade user to admin + payload = json.dumps({'access': 'admin'}) + r = api_as_admin.put(local_user_roles_path, data=payload) assert r.ok - session.params = { - 'user': user - } - r = session.get(url_get_not_auth) + + # User should now be able to access other roles + r = api_as_other_user.get(admin_user_roles_path) assert r.ok - session.params = { - 'user': adm_user - } - payload = json.dumps({'access':'rw'}) - r = session.put(url_get, data=payload) + + # Change user back to 'rw' access + payload = json.dumps({'access': 'rw'}) + r = api_as_admin.put(local_user_roles_path, data=payload) assert r.ok - session.params = { - 'user': user - } - r = session.get(url_get_not_auth) + + # User is now forbidden again + r = api_as_other_user.get(admin_user_roles_path) assert r.status_code == 403 - session.params = { - 'user': adm_user - } - r = session.delete(url_get) + + # Delete role + r = api_as_admin.delete(local_user_roles_path) assert r.ok - r = session.get(url_get) + + # Verify delete + r = api_as_admin.get(local_user_roles_path) assert r.status_code == 404 diff --git a/test/integration_tests/test_tags.py b/test/integration_tests/test_tags.py index 8d337c663..a8d0b9438 100644 --- a/test/integration_tests/test_tags.py +++ b/test/integration_tests/test_tags.py @@ -1,111 +1,67 @@ -import requests import json -import time -from nose.tools import with_setup import logging log = logging.getLogger(__name__) sh = logging.StreamHandler() log.addHandler(sh) -log.setLevel(logging.INFO) -adm_user = 'admin@user.com' -test_data = type('',(object,),{})() -base_url = 'http://localhost:8080/api' -session = None -def _build_url_and_payload(method, tag, newtag=None, requestor=adm_user): - if method == 'POST': - url = test_data.proj_url - payload = json.dumps({'value': tag}) - else: - url = test_data.proj_url + '/' + tag - payload = json.dumps({'value': newtag}) - return url, payload - -def setup_db(): - global session - session = requests.Session() - # all the requests will be performed as root - session.params = { - 'user': 'test@user.com', - 'root': True - } - - # Create a group - test_data.group_id = 'test_group_' + str(int(time.time()*1000)) - payload = { - '_id': test_data.group_id - } - payload = json.dumps(payload) - r = session.post(base_url + '/groups', data=payload) - assert r.ok - payload = { - 'group': test_data.group_id, - 'label': 'test_project', - 'public': False - } - payload = json.dumps(payload) - r = session.post(base_url + '/projects', data=payload) - test_data.pid = json.loads(r.content)['_id'] - assert r.ok - log.debug('pid = \'{}\''.format(test_data.pid)) - test_data.proj_url = base_url + '/projects/{}/tags'.format(test_data.pid) - -def teardown_db(): - r = session.delete(base_url + '/projects/' + test_data.pid) - assert r.ok - r = session.delete(base_url + '/groups/' + test_data.group_id) - assert r.ok - -@with_setup(setup_db, teardown_db) -def test_tags(): +def test_tags(with_a_group_and_a_project, api_as_admin): + data = with_a_group_and_a_project tag = 'test_tag' new_tag = 'new_test_tag' other_tag = 'other_test_tag' - url_get_tag, _ = _build_url_and_payload('GET', tag) - url_get_new, _ = _build_url_and_payload('GET', new_tag) - url_get_other, _ = _build_url_and_payload('GET', other_tag) - r = session.get(url_get_tag) + tags_path = '/projects/' + data.project_id + '/tags' + tag_path = tags_path + '/' + tag + new_tag_path = tags_path + '/' + new_tag + other_tag_path = tags_path + '/' + other_tag + + # Add tag and verify + r = api_as_admin.get(tag_path) assert r.status_code == 404 - url_post, payload = _build_url_and_payload('POST', tag) - r = session.post(url_post, data=payload) + payload = json.dumps({'value': tag}) + r = api_as_admin.post(tags_path, data=payload) assert r.ok - r = session.get(url_get_tag) + r = api_as_admin.get(tag_path) assert r.ok assert json.loads(r.content) == tag - url_post, payload = _build_url_and_payload('POST', new_tag) - r = session.post(url_post, data=payload) + # Add new tag and verify + payload = json.dumps({'value': new_tag}) + r = api_as_admin.post(tags_path, data=payload) assert r.ok - url_post, payload = _build_url_and_payload('POST', new_tag) - r = session.post(url_post, data=payload) + # Add a duplicate tag, returns 404 + payload = json.dumps({'value': new_tag}) + r = api_as_admin.post(tags_path, data=payload) assert r.status_code == 404 - r = session.get(url_get_new) + r = api_as_admin.get(new_tag_path) assert r.ok assert json.loads(r.content) == new_tag - url_put, payload = _build_url_and_payload('PUT', tag, new_tag) - r = session.put(url_put, data=payload) + # Attempt to update tag, returns 404 + payload = json.dumps({'value': new_tag}) + r = api_as_admin.put(tag_path, data=payload) assert r.status_code == 404 - r = session.get(url_get_other, verify=False) + # Update existing tag to other_tag + r = api_as_admin.get(other_tag_path) assert r.status_code == 404 - url_put, payload = _build_url_and_payload('PUT', tag, other_tag) - r = session.put(url_put, data=payload) + payload = json.dumps({'value': other_tag}) + r = api_as_admin.put(tag_path, data=payload) assert r.ok - r = session.get(url_get_other) + r = api_as_admin.get(other_tag_path) assert r.ok assert json.loads(r.content) == other_tag - - r = session.get(url_get_tag) + r = api_as_admin.get(tag_path) assert r.status_code == 404 - r = session.delete(url_get_other) # url for 'DELETE' is the same as the one for 'GET' + + # Cleanup + r = api_as_admin.delete(other_tag_path) # url for 'DELETE' is the same as the one for 'GET' assert r.ok - r = session.get(url_get_other) + r = api_as_admin.get(other_tag_path) assert r.status_code == 404 - r = session.delete(url_get_new) # url for 'DELETE' is the same as the one for 'GET' + r = api_as_admin.delete(new_tag_path) # url for 'DELETE' is the same as the one for 'GET' assert r.ok - r = session.get(url_get_new) + r = api_as_admin.get(new_tag_path) assert r.status_code == 404 diff --git a/test/integration_tests/test_users.py b/test/integration_tests/test_users.py index d5f4e541d..09d6f5956 100644 --- a/test/integration_tests/test_users.py +++ b/test/integration_tests/test_users.py @@ -1,35 +1,38 @@ -import requests import json import logging + log = logging.getLogger(__name__) sh = logging.StreamHandler() log.addHandler(sh) -requests.packages.urllib3.disable_warnings() -base_url = 'http://localhost:8080/api' +def test_users(api_as_admin): + new_user_id = 'new@user.com' -def test_users(): - _id = 'new@user.com' - r = requests.get(base_url + '/users/self?user=test@user.com') + # Get self + r = api_as_admin.get('/users/self') assert r.ok - r = requests.get(base_url + '/users/' + _id + '?user=test@user.com&root=true') + + # Add new user + r = api_as_admin.get('/users/' + new_user_id) assert r.status_code == 404 - payload = { - '_id': _id, + payload = json.dumps({ + '_id': new_user_id, 'firstname': 'New', 'lastname': 'User', - } - payload = json.dumps(payload) - r = requests.post(base_url + '/users?user=test@user.com&root=true', data=payload) + }) + r = api_as_admin.post('/users', data=payload) assert r.ok - r = requests.get(base_url + '/users/' + _id + '?user=test@user.com&root=true') + r = api_as_admin.get('/users/' + new_user_id) assert r.ok - payload = { + + # Modify existing user + payload = json.dumps({ 'firstname': 'Realname' - } - payload = json.dumps(payload) - r = requests.put(base_url + '/users/' + _id + '?user=test@user.com&root=true', data=payload) + }) + r = api_as_admin.put('/users/' + new_user_id, data=payload) assert r.ok - r = requests.delete(base_url + '/users/' + _id + '?user=test@user.com&root=true') + + # Cleanup + r = api_as_admin.delete('/users/' + new_user_id) assert r.ok diff --git a/test/requirements-integration-test.txt b/test/requirements-integration-test.txt new file mode 100644 index 000000000..6120ac2b0 --- /dev/null +++ b/test/requirements-integration-test.txt @@ -0,0 +1,22 @@ +# Development packages +coverage==4.0.3 +coveralls==1.1 +nose==1.3.7 +PasteScript==2.0.2 +pylint==1.5.3 +pytest==2.8.5 +pytest-cov==2.2.0 +pytest-watch==3.8.0 +pymongo==3.2 + +# Production packages +enum==0.4.6 +jsonschema==2.5.1 +Markdown==2.6.5 +pyOpenSSL==0.15.1 +python-dateutil==2.4.2 +pytz==2015.7 +requests==2.9.1 +rfc3987==1.3.4 +webapp2==2.5.2 +WebOb==1.5.1 From 38cdac4b4a4be6211434749d0cfd7082b44a3a6f Mon Sep 17 00:00:00 2001 From: Joe Schneider Date: Mon, 29 Feb 2016 17:41:57 -0600 Subject: [PATCH 4/8] Remove daemonized run --- .travis.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index ac0681d61..21ebe8099 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,11 +11,8 @@ install: - brew install python before_script: - bin/install.sh --ci - - bin/run.sh -d script: - bin/runtests.sh unit --ci - bin/runtests.sh integration --ci after_success: - coveralls -after_script: - - bin/run.sh -s From 0d79194a263fb2d9facac4c9efaf1b99e226c228 Mon Sep 17 00:00:00 2001 From: Joe Schneider Date: Tue, 1 Mar 2016 00:26:48 -0600 Subject: [PATCH 5/8] Add docker-compose dependency --- .travis.yml | 22 +++++++++++----------- bin/runtests.sh | 1 + 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/.travis.yml b/.travis.yml index 21ebe8099..c1f382a2e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,16 +1,16 @@ -#See https://github.com/travis-ci/travis-ci/issues/2312 for info on why we need -# to install python manually -# Python isn't supported OOTB, so pick a language that makes Travis happy -language: objective-c -os: osx -sudo: false -env: - - SCITRAN_RUNTIME_BOOTSTRAP=test/test_bootstrap.json +#Travis OSX currently doesn't not support docker (via virtualbox). +# "This computer doesn't have VT-X/AMD-v enabled." +sudo: required +dist: trusty install: - - brew update - - brew install python + - sudo apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D + - sudo sh -c "echo 'deb https://apt.dockerproject.org/repo ubuntu-trusty main' > /etc/apt/sources.list.d/docker.list" + - sudo apt-get update -qq + - sudo apt-get -o Dpkg::Options::="--force-confnew" install -y -q docker-engine + - sudo curl -o /usr/local/bin/docker-compose -L https://github.com/docker/compose/releases/download/1.6.2/docker-compose-`uname -s`-`uname -m` + - sudo chmod +x /usr/local/bin/docker-compose before_script: - - bin/install.sh --ci + - sudo bin/install.sh --ci script: - bin/runtests.sh unit --ci - bin/runtests.sh integration --ci diff --git a/bin/runtests.sh b/bin/runtests.sh index fac720f32..cbbd06219 100755 --- a/bin/runtests.sh +++ b/bin/runtests.sh @@ -1,4 +1,5 @@ #!/bin/bash +set -e unit_test_path=test/unit_tests/ integration_test_path=test/integration_tests/ From 9c5e1fa95f7919868d5cd7a7b03eabb86e3b543c Mon Sep 17 00:00:00 2001 From: Joe Schneider Date: Sat, 5 Mar 2016 14:15:22 -0600 Subject: [PATCH 6/8] Make changes to work on master, BF downloads --- bin/runtests.sh | 28 ++-------------------------- docker/Dockerfile | 2 +- test/docker-compose.yml | 18 +++++++++++++++++- 3 files changed, 20 insertions(+), 28 deletions(-) diff --git a/bin/runtests.sh b/bin/runtests.sh index cbbd06219..996ef0fbf 100755 --- a/bin/runtests.sh +++ b/bin/runtests.sh @@ -19,13 +19,13 @@ case "$1-$2" in PYTHONPATH=. ptw $unit_test_path $code_path --poll -- $unit_test_path ;; integration---ci|integration-) - docker-compose \ + docker-compose \ -f test/docker-compose.yml \ run \ --rm \ -e PYTHONPATH=/var/scitran/code/api \ --entrypoint /var/scitran/code/api/bin/bootstrap.py \ - scitran-core users /var/scitran/test-config/test_bootstrap.json && \ + bootstrap users /var/scitran/test-config/test_bootstrap.json && \ docker-compose -f test/docker-compose.yml run --rm integration-test docker-compose -f test/docker-compose.yml down ;; @@ -37,27 +37,3 @@ case "$1-$2" in ;; esac ) - -# -# Coverage not necessary -# Running wsgi container of some kind - use docker/Dockerfile -# Expose on random port - don't care -# Run mongodb container - use open source one with osx workaround... -# Create runtime environment in third container -# Use uwsgi container or use super small python env one? -# Run py.test there, connect to wsgi and mongodb -# How does wsgi container connect to mongodb? -# -# -# -# -# (api/)$ docker build -t scitran-core -f docker/Dockerfile . -# (api/)$ docker run --rm --name test-mongo mongo & -# (api/)$ docker run -e "SCITRAN_PERSISTENT_DB_URI=mongodb://test-mongo:27017/scitran" --link test-mongo --rm -v $(pwd)/test/test_bootstrap.json:/accounts.json scitran-core /var/scitran/code/api/bin/bootstrap.py users /accounts.json -# (api/)$ docker run --rm --name scitran-core -e "SCITRAN_PERSISTENT_DB_URI=mongodb://test-mongo:27017/scitran" -e "SCITRAN_CORE_INSECURE=true" -v $(pwd)/persistent/data:/var/scitran/data -v $(pwd):/var/scitran/code/api --link test-mongo scitran-core uwsgi --ini /var/scitran/config/uwsgi-config.ini --http 0.0.0.0:8080 --python-autoreload 1 & -# (test/)$ docker build -t integration-test . -# (test/integration_tests)$ docker run --link test-mongo --link scitran-core -v $(pwd):/usr/src/tests integration-test test_collection.py -# -# -# get to a prompt -# docker run --link test-mongo --link scitran-core -v $(pwd):/usr/src/tests -it --entrypoint=/bin/bash integration-test diff --git a/docker/Dockerfile b/docker/Dockerfile index bdd29e645..773805d17 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -88,4 +88,4 @@ RUN /inject_build_info.sh ${BRANCH_LABEL} ${COMMIT_HASH} \ ENTRYPOINT ["/var/scitran/uwsgi-entrypoint.sh"] -CMD ["uwsgi", "--ini", "/var/scitran/config/uwsgi-config.ini", "--http", "0.0.0.0:8080" ] +CMD ["uwsgi", "--ini", "/var/scitran/config/uwsgi-config.ini", "--http", "0.0.0.0:8080", "--http-keepalive", "--so-keepalive", "--add-header", "Connection: Keep-Alive" ] diff --git a/test/docker-compose.yml b/test/docker-compose.yml index 1b16758e5..9703475fa 100644 --- a/test/docker-compose.yml +++ b/test/docker-compose.yml @@ -1,18 +1,34 @@ version: '2' services: - scitran-core: + scitran-base: build: context: .. dockerfile: docker/Dockerfile + scitran-core: + extends: scitran-base links: - mongo environment: + - SCITRAN_CORE_DRONE_SECRET="changeme" - SCITRAN_PERSISTENT_DB_URI=mongodb://mongo:27017/scitran - SCITRAN_CORE_INSECURE=true - SCITRAN_CORE_LOG_LEVEL=debug + ports: + - "127.0.0.1:8080:8080" volumes: - .:/var/scitran/test-config - ..:/var/scitran/code/api/ + bootstrap: + extends: scitran-base + links: + - scitran-core + environment: + - SCITRAN_CORE_DRONE_SECRET="changeme" + - SCITRAN_RUNTIME_HOST=scitran-core + - SCITRAN_RUNTIME_PORT=8080 + - SCITRAN_RUNTIME_PROTO=http + volumes: + - .:/var/scitran/test-config mongo: image: mongo integration-test: From 9118332996a974594f6a20e4f8455d7e7296c43a Mon Sep 17 00:00:00 2001 From: Joe Schneider Date: Mon, 7 Mar 2016 16:13:44 -0600 Subject: [PATCH 7/8] Update code comment from PR review --- test/integration_tests/conftest.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/integration_tests/conftest.py b/test/integration_tests/conftest.py index c17bb6569..18ed318e6 100644 --- a/test/integration_tests/conftest.py +++ b/test/integration_tests/conftest.py @@ -103,7 +103,12 @@ def teardown_db(): def data_builder(api_as_admin): class DataBuilder: - # This madness allows us nicer reading code by auto-generating fucntions. + # This function is called whenever DataBuilder.create_X() or + # DataBuilder.delete_X() is called (those functions don't + # actually exist). It returns a callable object that does the right + # thing based on what X is. + # This madness allows significantly reduced copy/paste code and more + # readable tests. def __getattr__(self, name): parent_attribute = { 'group': '_id', From 65e1553f3e5f80693d51ff1324b25338fe15422f Mon Sep 17 00:00:00 2001 From: Ryan Sanford Date: Mon, 21 Mar 2016 06:46:21 -0500 Subject: [PATCH 8/8] Support latest bootstrapping requirements --- bin/runtests.sh | 4 +--- test/docker-compose.yml | 10 ++++------ 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/bin/runtests.sh b/bin/runtests.sh index 996ef0fbf..1d3e23c54 100755 --- a/bin/runtests.sh +++ b/bin/runtests.sh @@ -23,9 +23,7 @@ case "$1-$2" in -f test/docker-compose.yml \ run \ --rm \ - -e PYTHONPATH=/var/scitran/code/api \ - --entrypoint /var/scitran/code/api/bin/bootstrap.py \ - bootstrap users /var/scitran/test-config/test_bootstrap.json && \ + bootstrap && \ docker-compose -f test/docker-compose.yml run --rm integration-test docker-compose -f test/docker-compose.yml down ;; diff --git a/test/docker-compose.yml b/test/docker-compose.yml index 9703475fa..18e7f3238 100644 --- a/test/docker-compose.yml +++ b/test/docker-compose.yml @@ -9,10 +9,11 @@ services: links: - mongo environment: - - SCITRAN_CORE_DRONE_SECRET="changeme" + - SCITRAN_CORE_DRONE_SECRET=changeme - SCITRAN_PERSISTENT_DB_URI=mongodb://mongo:27017/scitran - SCITRAN_CORE_INSECURE=true - SCITRAN_CORE_LOG_LEVEL=debug + - SCITRAN_SITE_API_URL=http://127.0.0.1:8080/api ports: - "127.0.0.1:8080:8080" volumes: @@ -22,13 +23,10 @@ services: extends: scitran-base links: - scitran-core - environment: - - SCITRAN_CORE_DRONE_SECRET="changeme" - - SCITRAN_RUNTIME_HOST=scitran-core - - SCITRAN_RUNTIME_PORT=8080 - - SCITRAN_RUNTIME_PROTO=http volumes: - .:/var/scitran/test-config + - ..:/var/scitran/code/api + command: /var/scitran/code/api/bin/bootstrap.py --insecure --secret changeme http://scitran-core:8080/api /var/scitran/test-config/test_bootstrap.json mongo: image: mongo integration-test: