2016-10-12 14:44:14 +00:00
|
|
|
from .classes import BootTestCase
|
2016-10-07 23:07:47 +00:00
|
|
|
from rest_framework.test import APIClient
|
|
|
|
from rest_framework import status
|
|
|
|
|
2016-10-13 16:21:12 +00:00
|
|
|
from app.models import Project, Task
|
2016-10-18 20:23:10 +00:00
|
|
|
from nodeodm.models import ProcessingNode
|
2016-10-07 23:07:47 +00:00
|
|
|
from django.contrib.auth.models import User
|
|
|
|
|
2016-10-12 14:13:48 +00:00
|
|
|
class TestApi(BootTestCase):
|
2016-10-07 23:07:47 +00:00
|
|
|
def setUp(self):
|
2016-10-08 03:15:43 +00:00
|
|
|
pass
|
2016-10-07 23:07:47 +00:00
|
|
|
|
|
|
|
def tearDown(self):
|
|
|
|
pass
|
|
|
|
|
2016-10-22 15:23:37 +00:00
|
|
|
def test_projects_and_tasks(self):
|
2016-10-07 23:07:47 +00:00
|
|
|
client = APIClient()
|
2016-10-11 22:08:01 +00:00
|
|
|
|
2016-10-12 14:13:48 +00:00
|
|
|
user = User.objects.get(username="testuser")
|
|
|
|
self.assertFalse(user.is_superuser)
|
2016-10-11 22:08:01 +00:00
|
|
|
|
2016-10-08 03:15:43 +00:00
|
|
|
project = Project.objects.create(
|
2016-10-12 14:13:48 +00:00
|
|
|
owner=user,
|
2016-10-08 03:15:43 +00:00
|
|
|
name="test project"
|
|
|
|
)
|
2016-10-11 22:08:01 +00:00
|
|
|
other_project = Project.objects.create(
|
2016-10-12 14:13:48 +00:00
|
|
|
owner=User.objects.get(username="testuser2"),
|
2016-10-11 22:08:01 +00:00
|
|
|
name="another test project"
|
|
|
|
)
|
2016-10-07 23:07:47 +00:00
|
|
|
|
|
|
|
# Forbidden without credentials
|
|
|
|
res = client.get('/api/projects/')
|
|
|
|
self.assertEqual(res.status_code, status.HTTP_403_FORBIDDEN)
|
2016-10-11 22:08:01 +00:00
|
|
|
|
2016-10-12 14:13:48 +00:00
|
|
|
client.login(username="testuser", password="test1234")
|
2016-10-07 23:07:47 +00:00
|
|
|
res = client.get('/api/projects/')
|
|
|
|
self.assertEqual(res.status_code, status.HTTP_200_OK)
|
2016-10-08 00:46:19 +00:00
|
|
|
self.assertTrue(len(res.data["results"]) > 0)
|
2016-10-07 23:07:47 +00:00
|
|
|
|
2016-11-04 18:19:18 +00:00
|
|
|
# Can sort
|
|
|
|
res = client.get('/api/projects/?ordering=-created_at')
|
|
|
|
last_project = Project.objects.filter(owner=user).latest('created_at')
|
|
|
|
self.assertTrue(res.data["results"][0]['id'] == last_project.id)
|
|
|
|
|
2016-10-08 03:15:43 +00:00
|
|
|
res = client.get('/api/projects/{}/'.format(project.id))
|
2016-10-07 23:07:47 +00:00
|
|
|
self.assertEqual(res.status_code, status.HTTP_200_OK)
|
|
|
|
|
|
|
|
res = client.get('/api/projects/dasjkldas/')
|
|
|
|
self.assertEqual(res.status_code, status.HTTP_404_NOT_FOUND)
|
2016-10-11 22:08:01 +00:00
|
|
|
|
|
|
|
res = client.get('/api/projects/{}/'.format(other_project.id))
|
2016-10-12 14:13:48 +00:00
|
|
|
self.assertEqual(res.status_code, status.HTTP_404_NOT_FOUND)
|
2016-10-11 22:08:01 +00:00
|
|
|
|
|
|
|
# Can filter
|
2016-10-13 16:21:12 +00:00
|
|
|
res = client.get('/api/projects/?owner=999')
|
2016-10-11 22:08:01 +00:00
|
|
|
self.assertEqual(res.status_code, status.HTTP_200_OK)
|
|
|
|
self.assertTrue(len(res.data["results"]) == 0)
|
|
|
|
|
|
|
|
# Cannot list somebody else's project without permission
|
|
|
|
res = client.get('/api/projects/?id={}'.format(other_project.id))
|
|
|
|
self.assertEqual(res.status_code, status.HTTP_200_OK)
|
|
|
|
self.assertTrue(len(res.data["results"]) == 0)
|
2016-10-13 16:21:12 +00:00
|
|
|
|
|
|
|
# Can access individual project
|
|
|
|
res = client.get('/api/projects/{}/'.format(project.id))
|
|
|
|
self.assertEqual(res.status_code, status.HTTP_200_OK)
|
|
|
|
self.assertTrue(res.data["id"] == project.id)
|
|
|
|
|
|
|
|
# Cannot access project for which we have no access to
|
|
|
|
res = client.get('/api/projects/{}/'.format(other_project.id))
|
|
|
|
self.assertEqual(res.status_code, status.HTTP_404_NOT_FOUND)
|
|
|
|
|
|
|
|
|
|
|
|
# Create some tasks
|
|
|
|
task = Task.objects.create(project=project)
|
|
|
|
task2 = Task.objects.create(project=project)
|
|
|
|
other_task = Task.objects.create(project=other_project)
|
|
|
|
|
|
|
|
# Can list project tasks to a project we have access to
|
|
|
|
res = client.get('/api/projects/{}/tasks/'.format(project.id))
|
|
|
|
self.assertEqual(res.status_code, status.HTTP_200_OK)
|
|
|
|
self.assertTrue(len(res.data) == 2)
|
|
|
|
|
2016-10-27 16:26:15 +00:00
|
|
|
# Can sort
|
2016-11-04 18:19:18 +00:00
|
|
|
res = client.get('/api/projects/{}/tasks/?ordering=created_at'.format(project.id))
|
2016-10-27 16:26:15 +00:00
|
|
|
self.assertTrue(res.data[0]['id'] == task.id)
|
|
|
|
self.assertTrue(res.data[1]['id'] == task2.id)
|
|
|
|
|
2016-11-04 18:19:18 +00:00
|
|
|
res = client.get('/api/projects/{}/tasks/?ordering=-created_at'.format(project.id))
|
2016-10-27 16:26:15 +00:00
|
|
|
self.assertTrue(res.data[0]['id'] == task2.id)
|
|
|
|
self.assertTrue(res.data[1]['id'] == task.id)
|
|
|
|
|
2016-10-13 16:21:12 +00:00
|
|
|
# Cannot list project tasks for a project we don't have access to
|
|
|
|
res = client.get('/api/projects/{}/tasks/'.format(other_project.id))
|
|
|
|
self.assertEqual(res.status_code, status.HTTP_404_NOT_FOUND)
|
|
|
|
|
|
|
|
# Cannot list project tasks for a project that doesn't exist
|
|
|
|
res = client.get('/api/projects/999/tasks/')
|
|
|
|
self.assertEqual(res.status_code, status.HTTP_404_NOT_FOUND)
|
|
|
|
|
|
|
|
# Can list task details for a task belonging to a project we have access to
|
|
|
|
res = client.get('/api/projects/{}/tasks/{}/'.format(project.id, task.id))
|
|
|
|
self.assertEqual(res.status_code, status.HTTP_200_OK)
|
|
|
|
self.assertTrue(res.data["id"] == task.id)
|
|
|
|
|
2016-10-27 16:26:15 +00:00
|
|
|
# images_count field exists
|
|
|
|
self.assertTrue(res.data["images_count"] == 0)
|
|
|
|
|
2016-10-31 21:09:01 +00:00
|
|
|
# Get console output
|
2016-11-02 22:32:24 +00:00
|
|
|
res = client.get('/api/projects/{}/tasks/{}/output/'.format(project.id, task.id))
|
2016-10-31 21:09:01 +00:00
|
|
|
self.assertEqual(res.status_code, status.HTTP_200_OK)
|
|
|
|
self.assertTrue(res.data == "")
|
|
|
|
|
|
|
|
task.console_output = "line1\nline2\nline3"
|
|
|
|
task.save()
|
|
|
|
|
2016-11-02 22:32:24 +00:00
|
|
|
res = client.get('/api/projects/{}/tasks/{}/output/'.format(project.id, task.id))
|
2016-10-31 21:09:01 +00:00
|
|
|
self.assertEqual(res.status_code, status.HTTP_200_OK)
|
|
|
|
self.assertTrue(res.data == task.console_output)
|
|
|
|
|
|
|
|
# Console output with line num
|
2016-11-02 22:32:24 +00:00
|
|
|
res = client.get('/api/projects/{}/tasks/{}/output/?line=2'.format(project.id, task.id))
|
2016-10-31 21:09:01 +00:00
|
|
|
self.assertTrue(res.data == "line3")
|
|
|
|
|
|
|
|
# Console output with line num out of bounds
|
2016-11-02 22:32:24 +00:00
|
|
|
res = client.get('/api/projects/{}/tasks/{}/output/?line=3'.format(project.id, task.id))
|
2016-10-31 21:09:01 +00:00
|
|
|
self.assertTrue(res.data == "")
|
2016-11-02 22:32:24 +00:00
|
|
|
res = client.get('/api/projects/{}/tasks/{}/output/?line=-1'.format(project.id, task.id))
|
2016-10-31 21:09:01 +00:00
|
|
|
self.assertTrue(res.data == task.console_output)
|
|
|
|
|
2016-10-13 16:21:12 +00:00
|
|
|
# Cannot list task details for a task belonging to a project we don't have access to
|
|
|
|
res = client.get('/api/projects/{}/tasks/{}/'.format(other_project.id, other_task.id))
|
|
|
|
self.assertEqual(res.status_code, status.HTTP_404_NOT_FOUND)
|
|
|
|
|
|
|
|
# As above, but by trying to trick the API by using a project we have access to
|
|
|
|
res = client.get('/api/projects/{}/tasks/{}/'.format(project.id, other_task.id))
|
|
|
|
self.assertEqual(res.status_code, status.HTTP_404_NOT_FOUND)
|
|
|
|
|
|
|
|
# Cannot access task details for a task that doesn't exist
|
|
|
|
res = client.get('/api/projects/{}/tasks/999/'.format(project.id, other_task.id))
|
2016-10-18 20:23:10 +00:00
|
|
|
self.assertEqual(res.status_code, status.HTTP_404_NOT_FOUND)
|
|
|
|
|
2016-10-22 15:23:37 +00:00
|
|
|
# Can update a task
|
|
|
|
res = client.patch('/api/projects/{}/tasks/{}/'.format(project.id, task.id), {'name': 'updated!'}, format='json')
|
|
|
|
self.assertEqual(res.status_code, status.HTTP_200_OK)
|
|
|
|
|
|
|
|
# Verify the task has been updated
|
|
|
|
res = client.get('/api/projects/{}/tasks/{}/'.format(project.id, task.id))
|
|
|
|
self.assertTrue(res.data["name"] == "updated!")
|
|
|
|
|
|
|
|
# Cannot update a task we have no access to
|
|
|
|
res = client.patch('/api/projects/{}/tasks/{}/'.format(other_project.id, other_task.id), {'name': 'updated!'}, format='json')
|
|
|
|
self.assertEqual(res.status_code, status.HTTP_404_NOT_FOUND)
|
|
|
|
|
2016-11-02 22:32:24 +00:00
|
|
|
# Can cancel a task for which we have permission
|
|
|
|
self.assertTrue(task.pending_action is None)
|
|
|
|
res = client.post('/api/projects/{}/tasks/{}/cancel/'.format(project.id, task.id))
|
|
|
|
self.assertTrue(res.data["success"])
|
|
|
|
task.refresh_from_db()
|
|
|
|
self.assertTrue(task.last_error is None)
|
|
|
|
self.assertTrue(task.pending_action == task.PendingActions.CANCEL)
|
|
|
|
|
|
|
|
# Cannot cancel a task for which we don't have permission
|
|
|
|
res = client.post('/api/projects/{}/tasks/{}/cancel/'.format(other_project.id, other_task.id))
|
|
|
|
self.assertEqual(res.status_code, status.HTTP_404_NOT_FOUND)
|
|
|
|
|
2016-11-04 18:19:18 +00:00
|
|
|
# TODO: test restart and delete operations
|
|
|
|
|
2016-10-18 20:23:10 +00:00
|
|
|
|
|
|
|
def test_processingnodes(self):
|
|
|
|
client = APIClient()
|
|
|
|
|
|
|
|
pnode = ProcessingNode.objects.create(
|
|
|
|
hostname="localhost",
|
|
|
|
port=999
|
|
|
|
)
|
|
|
|
|
|
|
|
# Cannot list processing nodes as guest
|
|
|
|
res = client.get('/api/processingnodes/')
|
|
|
|
self.assertEqual(res.status_code, status.HTTP_403_FORBIDDEN)
|
|
|
|
|
|
|
|
res = client.get('/api/processingnodes/{}/'.format(pnode.id))
|
|
|
|
self.assertEqual(res.status_code, status.HTTP_403_FORBIDDEN)
|
|
|
|
|
|
|
|
client.login(username="testuser", password="test1234")
|
|
|
|
|
|
|
|
# Can list processing nodes as normal user
|
|
|
|
res = client.get('/api/processingnodes/')
|
|
|
|
self.assertEqual(res.status_code, status.HTTP_200_OK)
|
|
|
|
self.assertTrue(len(res.data) == 1)
|
|
|
|
self.assertTrue(res.data[0]["hostname"] == "localhost")
|
|
|
|
|
2016-10-24 18:14:35 +00:00
|
|
|
# Can use filters
|
|
|
|
res = client.get('/api/processingnodes/?id={}'.format(pnode.id))
|
|
|
|
self.assertEqual(res.status_code, status.HTTP_200_OK)
|
|
|
|
self.assertTrue(len(res.data) == 1)
|
|
|
|
|
2016-10-29 16:09:35 +00:00
|
|
|
# Can filter nodes with valid options
|
2016-10-27 13:25:21 +00:00
|
|
|
res = client.get('/api/processingnodes/?has_available_options=true')
|
2016-10-24 18:14:35 +00:00
|
|
|
self.assertEqual(res.status_code, status.HTTP_200_OK)
|
|
|
|
self.assertTrue(len(res.data) == 0)
|
|
|
|
|
2016-10-27 13:25:21 +00:00
|
|
|
res = client.get('/api/processingnodes/?has_available_options=false')
|
2016-10-24 18:14:35 +00:00
|
|
|
self.assertEqual(res.status_code, status.HTTP_200_OK)
|
2016-10-29 16:09:35 +00:00
|
|
|
self.assertTrue(len(res.data) == 1)
|
|
|
|
self.assertTrue(res.data[0]['hostname'] == 'localhost')
|
|
|
|
|
2016-10-24 18:14:35 +00:00
|
|
|
|
2016-10-18 20:23:10 +00:00
|
|
|
# Can get single processing node as normal user
|
|
|
|
res = client.get('/api/processingnodes/{}/'.format(pnode.id))
|
|
|
|
self.assertEqual(res.status_code, status.HTTP_200_OK)
|
|
|
|
self.assertTrue(res.data["hostname"] == "localhost")
|
|
|
|
|
2016-10-24 18:14:35 +00:00
|
|
|
|
2016-10-18 20:23:10 +00:00
|
|
|
# Cannot delete a processing node as normal user
|
|
|
|
res = client.delete('/api/processingnodes/{}/'.format(pnode.id))
|
|
|
|
self.assertTrue(res.status_code, status.HTTP_403_FORBIDDEN)
|
|
|
|
|
|
|
|
# Cannot create a processing node as normal user
|
|
|
|
res = client.post('/api/processingnodes/', {'hostname': 'localhost', 'port':'1000'})
|
|
|
|
self.assertTrue(res.status_code, status.HTTP_403_FORBIDDEN)
|
|
|
|
|
|
|
|
client.login(username="testsuperuser", password="test1234")
|
|
|
|
|
|
|
|
# Can delete a processing node as super user
|
|
|
|
res = client.delete('/api/processingnodes/{}/'.format(pnode.id))
|
|
|
|
self.assertTrue(res.status_code, status.HTTP_200_OK)
|
|
|
|
|
|
|
|
# Can create a processing node as super user
|
|
|
|
res = client.post('/api/processingnodes/', {'hostname': 'localhost', 'port':'1000'})
|
|
|
|
self.assertTrue(res.status_code, status.HTTP_200_OK)
|
|
|
|
|
|
|
|
# Verify node has been created
|
|
|
|
res = client.get('/api/processingnodes/')
|
|
|
|
self.assertEqual(res.status_code, status.HTTP_200_OK)
|
|
|
|
self.assertTrue(len(res.data) == 1)
|
2016-10-21 15:02:41 +00:00
|
|
|
self.assertTrue(res.data[0]["port"] == 1000)
|
|
|
|
|