blob: 18fe1599350c4532c70cbe01bb0bf8b581ecf856 [file] [log] [blame] [edit]
# Check that the LNT REST JSON API is working.
# create temporary instance
# RUN: rm -rf %t.instance
# RUN: python %{shared_inputs}/create_temp_instance.py \
# RUN: %s %{shared_inputs}/SmallInstance \
# RUN: %t.instance %S/Inputs/V4Pages_extra_records.sql
#
# RUN: python %s %t.instance %{shared_inputs}
import json
import logging
import sys
import unittest
import lnt.server.db.migrate
import lnt.server.ui.app
from V4Pages import check_json
logging.basicConfig(level=logging.INFO)
class _hashabledict(dict):
"""See https://stackoverflow.com/questions/1151658."""
def __hash__(self):
return hash(tuple(sorted(self.items())))
class JSONAPIDeleteTester(unittest.TestCase):
"""Test the REST api."""
def setUp(self):
"""Bind to the LNT test instance."""
_, instance_path, shared_inputs = sys.argv
app = lnt.server.ui.app.App.create_standalone(instance_path)
app.testing = True
self.client = app.test_client()
self.shared_inputs = shared_inputs
def test_00_update_machine(self):
"""Check PUT request to /machines/n"""
client = self.client
# We are going to set the 'os' field to none, remove the 'uname'
# parameter and add the 'new_parameter' parameter.
# Make sure none of those things happened yet:
machine_before = check_json(client, 'api/db_default/v4/nts/machines/1')
machine_before = machine_before['machine']
self.assertIsNotNone(machine_before.get('os', None))
self.assertIsNone(machine_before.get('new_parameter', None))
self.assertIsNotNone(machine_before.get('uname', None))
data = {
'machine': {
'hardware': 'hal 9000',
'os': None,
'hostname': 'localhost',
'new_parameter': True,
},
}
json_data = json.dumps(data)
resp = client.put('api/db_default/v4/nts/machines/1', data=json_data,
headers={'AuthToken': 'test_token'})
self.assertEqual(resp.status_code, 200)
machine_after = check_json(client, 'api/db_default/v4/nts/machines/1')
machine_after = machine_after['machine']
for key in ('hardware', 'os', 'hostname', 'new_parameter', 'uname'):
self.assertEqual(machine_after.get(key, None),
data['machine'].get(key, None))
def test_00_rename_machine(self):
"""Check rename POST request to /machines/n"""
client = self.client
# Make sure the environment is as expected.
j = check_json(client, 'api/db_default/v4/nts/machines/1')
self.assertEqual(j['machine']['name'], 'localhost__clang_DEV__x86_64')
data = {
'action': 'rename',
'name': 'new_machine_name',
}
resp = client.post('api/db_default/v4/nts/machines/1', data=data)
self.assertEqual(resp.status_code, 401)
resp = client.post('api/db_default/v4/nts/machines/1', data=data,
headers={'AuthToken': 'wrong token'})
self.assertEqual(resp.status_code, 401)
resp = client.post('api/db_default/v4/nts/machines/1', data=data,
headers={'AuthToken': 'test_token'})
self.assertEqual(resp.status_code, 200)
# Machine should be renamed now.
j = check_json(client, 'api/db_default/v4/nts/machines/1')
self.assertEqual(j['machine']['name'], 'new_machine_name')
def test_01_delete_run(self):
"""Check /runs/n can be deleted."""
client = self.client
j = check_json(client, 'api/db_default/v4/nts/runs/1')
sample_ids = [s['id'] for s in j['tests']]
self.assertNotEqual(len(sample_ids), 0)
for sid in sample_ids:
resp = client.get('api/db_default/v4/nts/samples/{}'.format(sid))
self.assertEqual(resp.status_code, 200)
resp = client.delete('api/db_default/v4/nts/runs/1')
self.assertEqual(resp.status_code, 401)
resp = client.delete('api/db_default/v4/nts/runs/1',
headers={'AuthToken': 'wrong token'})
self.assertEqual(resp.status_code, 401)
resp = client.delete('api/db_default/v4/nts/runs/1',
headers={'AuthToken': 'test_token'})
self.assertEqual(resp.status_code, 200)
resp = client.get('api/db_default/v4/nts/runs/1')
self.assertEqual(resp.status_code, 404)
for sid in sample_ids:
resp = client.get('api/db_default/v4/nts/samples/{}'.format(sid))
self.assertEqual(resp.status_code, 404)
def test_02_delete_machine(self):
"""Check /machines/n can be deleted."""
client = self.client
j = check_json(client, 'api/db_default/v4/nts/machines/2')
run_ids = [s['id'] for s in j['runs']]
self.assertNotEqual(len(run_ids), 0)
sample_ids = []
for run_id in run_ids:
resp = check_json(client,
'api/db_default/v4/nts/runs/{}'.format(run_id))
sample_ids.append([s['id'] for s in resp['tests']])
self.assertNotEqual(len(sample_ids), 0)
resp = client.delete('api/db_default/v4/nts/machines/2')
self.assertEqual(resp.status_code, 401)
resp = client.delete('api/db_default/v4/nts/machines/2',
headers={'AuthToken': 'wrong token'})
self.assertEqual(resp.status_code, 401)
resp = client.delete('api/db_default/v4/nts/machines/2',
headers={'AuthToken': 'test_token'})
self.assertEqual(resp.status_code, 200)
self.assertEqual(resp.get_data(as_text=True),
'''Deleting runs 3 5 6 7 8 9 (6/6)
Deleted machine machine2:2
''')
resp = client.get('api/db_default/v4/nts/machines/2')
self.assertEqual(resp.status_code, 404)
for run_id in run_ids:
resp = client.get('api/db_default/v4/nts/runs/{}'.format(run_id))
self.assertEqual(resp.status_code, 404)
for sid in sample_ids:
resp = client.get('api/db_default/v4/nts/samples/{}'.format(sid))
self.assertEqual(resp.status_code, 404)
def test_03_post_run(self):
"""Check POST to /runs."""
client = self.client
resp = client.get('api/db_default/v4/nts/runs/5')
self.assertEqual(resp.status_code, 404)
data = open('%s/sample-report.json' % self.shared_inputs).read()
resp = client.post('api/db_default/v4/nts/runs', data=data)
self.assertEqual(resp.status_code, 401)
resp = client.post('api/db_default/v4/nts/runs', data=data,
headers={'AuthToken': 'test_token'})
self.assertEqual(resp.status_code, 301)
self.assertIn('http://localhost/api/db_default/v4/nts/runs/', resp.headers['Location'])
resp_json = json.loads(resp.data)
self.assertEqual(resp_json['run_id'], 5)
# Provoke a failing submission.
resp = client.post('api/db_default/v4/nts/runs?merge=reject',
data=data,
headers={'AuthToken': 'test_token'})
self.assertEqual(resp.status_code, 400)
resp_json = json.loads(resp.data)
self.assertEqual(resp_json['error'],
"import failure: Duplicate submission for '1'")
self.assertEqual(resp_json['success'], False)
def test_04_merge_into(self):
"""Check POST/merge into request for /machines."""
client = self.client
# Download existing machines.
machine_1 = check_json(client, 'api/db_default/v4/nts/machines/1')
machine_3 = check_json(client, 'api/db_default/v4/nts/machines/3')
# The test is boring if we don't have at least 1 run in each machine.
self.assertTrue(len(machine_1['runs']) > 0)
self.assertTrue(len(machine_3['runs']) > 0)
data = {
'action': 'merge',
'into': '3',
}
resp = client.post('api/db_default/v4/nts/machines/1', data=data,
headers={'AuthToken': 'test_token'})
self.assertEqual(resp.status_code, 200)
# Old machine should have disappeared.
resp_2 = client.get('api/db_default/v4/nts/machines/1')
self.assertEqual(resp_2.status_code, 404)
# The other machine should have the union of all runs.
machine_1['runs'] = [_hashabledict(run) for run in machine_1['runs']]
machine_3['runs'] = [_hashabledict(run) for run in machine_3['runs']]
allruns = set(machine_1['runs']).union(machine_3['runs'])
resp_3 = check_json(client, 'api/db_default/v4/nts/machines/3')
resp_3['runs'] = [_hashabledict(run) for run in resp_3['runs']]
self.assertEqual(set(resp_3['runs']), allruns)
if __name__ == '__main__':
unittest.main(argv=[sys.argv[0], ])