You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1144 lines
46 KiB
Python
1144 lines
46 KiB
Python
|
|
# Copyright (C) 2021-2022 Intel Corporation
|
|
#
|
|
# SPDX-License-Identifier: MIT
|
|
|
|
import json
|
|
from collections import OrderedDict
|
|
from io import BytesIO
|
|
from typing import Dict, Optional
|
|
from unittest import mock, skip
|
|
import os
|
|
|
|
import requests
|
|
from django.contrib.auth.models import Group, User
|
|
from django.http import HttpResponseNotFound, HttpResponseServerError
|
|
from PIL import Image
|
|
from rest_framework import status
|
|
from rest_framework.test import APIClient, APITestCase
|
|
|
|
from cvat.apps.engine.tests.utils import get_paginated_collection
|
|
|
|
LAMBDA_ROOT_PATH = '/api/lambda'
|
|
LAMBDA_FUNCTIONS_PATH = f'{LAMBDA_ROOT_PATH}/functions'
|
|
LAMBDA_REQUESTS_PATH = f'{LAMBDA_ROOT_PATH}/requests'
|
|
|
|
id_function_detector = "test-openvino-omz-public-yolo-v3-tf"
|
|
id_function_reid_response_data = "test-openvino-omz-intel-person-reidentification-retail-0300"
|
|
id_function_reid_response_no_data = "test-openvino-omz-intel-person-reidentification-retail-1234"
|
|
id_function_interactor = "test-openvino-dextr"
|
|
id_function_tracker = "test-pth-foolwood-siammask"
|
|
id_function_non_type = "test-model-has-non-type"
|
|
id_function_wrong_type = "test-model-has-wrong-type"
|
|
id_function_unknown_type = "test-model-has-unknown-type"
|
|
id_function_non_unique_labels = "test-model-has-non-unique-labels"
|
|
id_function_state_building = "test-model-has-state-building"
|
|
id_function_state_error = "test-model-has-state-error"
|
|
|
|
expected_keys_in_response_all_functions = ["id", "kind", "labels", "description", "framework", "name"]
|
|
expected_keys_in_response_function_interactor = expected_keys_in_response_all_functions + ["min_pos_points", "startswith_box"]
|
|
expected_keys_in_response_function_tracker = expected_keys_in_response_all_functions + ["state"]
|
|
expected_keys_in_response_requests = ["id", "function", "status", "progress", "enqueued", "started", "ended", "exc_info"]
|
|
|
|
path = os.path.join(os.path.dirname(__file__), 'assets', 'tasks.json')
|
|
with open(path) as f:
|
|
tasks = json.load(f)
|
|
|
|
# removed unnecessary data
|
|
path = os.path.join(os.path.dirname(__file__), 'assets', 'functions.json')
|
|
with open(path) as f:
|
|
functions = json.load(f)
|
|
|
|
|
|
def generate_image_file(filename, size=(100, 100)):
|
|
f = BytesIO()
|
|
image = Image.new('RGB', size=size)
|
|
image.save(f, 'jpeg')
|
|
f.name = filename
|
|
f.seek(0)
|
|
return f
|
|
|
|
|
|
class ForceLogin:
|
|
def __init__(self, user, client):
|
|
self.user = user
|
|
self.client = client
|
|
|
|
def __enter__(self):
|
|
if self.user:
|
|
self.client.force_login(self.user, backend='django.contrib.auth.backends.ModelBackend')
|
|
|
|
return self
|
|
|
|
def __exit__(self, exception_type, exception_value, traceback):
|
|
if self.user:
|
|
self.client.logout()
|
|
|
|
class _LambdaTestCaseBase(APITestCase):
|
|
def setUp(self):
|
|
self.client = APIClient()
|
|
|
|
http_patcher = mock.patch('cvat.apps.lambda_manager.views.LambdaGateway._http', side_effect = self.__get_data_from_lambda_manager_http)
|
|
self.addCleanup(http_patcher.stop)
|
|
http_patcher.start()
|
|
|
|
invoke_patcher = mock.patch('cvat.apps.lambda_manager.views.LambdaGateway.invoke', side_effect = self.__invoke_function)
|
|
self.addCleanup(invoke_patcher.stop)
|
|
invoke_patcher.start()
|
|
|
|
def __get_data_from_lambda_manager_http(self, **kwargs):
|
|
url = kwargs["url"]
|
|
if url == "/api/functions":
|
|
return functions["positive"]
|
|
else:
|
|
func_id = url.split("/")[-1]
|
|
if func_id in functions["positive"]:
|
|
if func_id in [id_function_state_building, id_function_state_error]:
|
|
r = requests.RequestException()
|
|
r.response = HttpResponseServerError()
|
|
raise r # raise 500 Internal_Server error
|
|
|
|
return functions["positive"][func_id]
|
|
else:
|
|
r = requests.HTTPError()
|
|
r.response = HttpResponseNotFound()
|
|
raise r # raise 404 Not Found error
|
|
|
|
def __invoke_function(self, func, payload):
|
|
data = []
|
|
func_id = func.id
|
|
type_function = functions["positive"][func_id]["metadata"]["annotations"]["type"]
|
|
if type_function == "reid":
|
|
if func_id == id_function_reid_response_data:
|
|
data = [0, 1]
|
|
else:
|
|
data = []
|
|
elif type_function == "tracker":
|
|
data = {
|
|
"shape": [12.34, 34.0, 35.01, 41.99],
|
|
"state": {"key": "value"},
|
|
}
|
|
elif type_function == "interactor":
|
|
data = [
|
|
[8, 12],
|
|
[34, 56],
|
|
[77, 77],
|
|
]
|
|
elif type_function == "detector":
|
|
data = [
|
|
{'confidence': '0.9959098', 'label': 'car', 'points': [3, 3, 15, 15], 'type': 'rectangle'},
|
|
{'confidence': '0.89535173', 'label': 'car', 'points': [20, 25, 30, 35], 'type': 'rectangle'},
|
|
{'confidence': '0.59464583', 'label': 'car', 'points': [12.17, 45.0, 69.80, 18.99], 'type': 'polygon'},
|
|
]
|
|
|
|
return data
|
|
|
|
@classmethod
|
|
def _create_db_users(cls):
|
|
(group_admin, _) = Group.objects.get_or_create(name="admin")
|
|
(group_user, _) = Group.objects.get_or_create(name="business")
|
|
|
|
user_admin = User.objects.create_superuser(username="admin", email="",
|
|
password="admin")
|
|
user_admin.groups.add(group_admin)
|
|
user_dummy = User.objects.create_user(username="user", password="user",
|
|
email="user@example.com")
|
|
user_dummy.groups.add(group_user)
|
|
|
|
cls.admin = user_admin
|
|
cls.user = user_dummy
|
|
|
|
|
|
def _create_task(self, data, image_data, *, owner=None, org_id=None):
|
|
with ForceLogin(owner or self.admin, self.client):
|
|
response = self.client.post('/api/tasks', data=data, format="json",
|
|
QUERY_STRING=f'org_id={org_id}' if org_id is not None else None)
|
|
assert response.status_code == status.HTTP_201_CREATED, response.status_code
|
|
tid = response.data["id"]
|
|
|
|
response = self.client.post("/api/tasks/%s/data" % tid,
|
|
data=image_data,
|
|
QUERY_STRING=f'org_id={org_id}' if org_id is not None else None)
|
|
assert response.status_code == status.HTTP_202_ACCEPTED, response.status_code
|
|
|
|
response = self.client.get("/api/tasks/%s" % tid,
|
|
QUERY_STRING=f'org_id={org_id}' if org_id is not None else None)
|
|
task = response.data
|
|
|
|
return task
|
|
|
|
|
|
def _generate_task_images(self, count): # pylint: disable=no-self-use
|
|
images = {
|
|
"client_files[%d]" % i: generate_image_file("image_%d.jpg" % i)
|
|
for i in range(count)
|
|
}
|
|
images["image_quality"] = 75
|
|
return images
|
|
|
|
|
|
@classmethod
|
|
def setUpTestData(cls):
|
|
cls._create_db_users()
|
|
|
|
|
|
def _get_request(self, path, user, *, org_id=None):
|
|
with ForceLogin(user, self.client):
|
|
response = self.client.get(path,
|
|
QUERY_STRING=f'org_id={org_id}' if org_id is not None else '')
|
|
return response
|
|
|
|
|
|
def _delete_request(self, path, user, *, org_id=None):
|
|
with ForceLogin(user, self.client):
|
|
response = self.client.delete(path,
|
|
QUERY_STRING=f'org_id={org_id}' if org_id is not None else '')
|
|
return response
|
|
|
|
|
|
def _post_request(self, path, user, data, *, org_id=None):
|
|
data = json.dumps(data)
|
|
with ForceLogin(user, self.client):
|
|
response = self.client.post(path, data=data, content_type='application/json',
|
|
QUERY_STRING=f'org_id={org_id}' if org_id is not None else '')
|
|
return response
|
|
|
|
|
|
def _patch_request(self, path, user, data, *, org_id=None):
|
|
data = json.dumps(data)
|
|
with ForceLogin(user, self.client):
|
|
response = self.client.patch(path, data=data, content_type='application/json',
|
|
QUERY_STRING=f'org_id={org_id}' if org_id is not None else '')
|
|
return response
|
|
|
|
|
|
def _check_expected_keys_in_response_function(self, data):
|
|
kind = data["kind"]
|
|
if kind == "interactor":
|
|
for key in expected_keys_in_response_function_interactor:
|
|
self.assertIn(key, data)
|
|
elif kind == "tracker":
|
|
for key in expected_keys_in_response_function_tracker:
|
|
self.assertIn(key, data)
|
|
else:
|
|
for key in expected_keys_in_response_all_functions:
|
|
self.assertIn(key, data)
|
|
|
|
|
|
class LambdaTestCases(_LambdaTestCaseBase):
|
|
def setUp(self):
|
|
super().setUp()
|
|
|
|
images_main_task = self._generate_task_images(3)
|
|
images_assigneed_to_user_task = self._generate_task_images(3)
|
|
self.main_task = self._create_task(tasks["main"], images_main_task)
|
|
self.assigneed_to_user_task = self._create_task(
|
|
tasks["assigneed_to_user"], images_assigneed_to_user_task
|
|
)
|
|
|
|
def test_api_v2_lambda_functions_list(self):
|
|
response = self._get_request(LAMBDA_FUNCTIONS_PATH, self.admin)
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
for data in response.data:
|
|
self._check_expected_keys_in_response_function(data)
|
|
|
|
response = self._get_request(LAMBDA_FUNCTIONS_PATH, self.user)
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
for data in response.data:
|
|
self._check_expected_keys_in_response_function(data)
|
|
|
|
response = self._get_request(LAMBDA_FUNCTIONS_PATH, None)
|
|
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
|
|
|
|
|
|
@mock.patch('cvat.apps.lambda_manager.views.LambdaGateway._http', return_value = {})
|
|
def test_api_v2_lambda_functions_list_empty(self, mock_http):
|
|
response = self._get_request(LAMBDA_FUNCTIONS_PATH, self.admin)
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
self.assertEqual(len(response.data), 0)
|
|
|
|
response = self._get_request(LAMBDA_FUNCTIONS_PATH, self.user)
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
self.assertEqual(len(response.data), 0)
|
|
|
|
response = self._get_request(LAMBDA_FUNCTIONS_PATH, None)
|
|
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
|
|
|
|
|
|
@mock.patch('cvat.apps.lambda_manager.views.LambdaGateway._http', return_value = functions["negative"])
|
|
def test_api_v2_lambda_functions_list_wrong(self, mock_http):
|
|
response = self._get_request(LAMBDA_FUNCTIONS_PATH, self.admin)
|
|
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
|
|
|
|
|
def test_api_v2_lambda_functions_read(self):
|
|
ids_functions = [id_function_detector, id_function_interactor,\
|
|
id_function_tracker, id_function_reid_response_data, \
|
|
id_function_non_type, id_function_wrong_type, id_function_unknown_type]
|
|
|
|
for id_func in ids_functions:
|
|
path = f'{LAMBDA_FUNCTIONS_PATH}/{id_func}'
|
|
|
|
response = self._get_request(path, self.admin)
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
self._check_expected_keys_in_response_function(response.data)
|
|
|
|
response = self._get_request(path, self.user)
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
self._check_expected_keys_in_response_function(response.data)
|
|
|
|
response = self._get_request(path, None)
|
|
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
|
|
|
|
|
|
def test_api_v2_lambda_functions_read_wrong_id(self):
|
|
id_wrong_function = "test-functions-wrong-id"
|
|
response = self._get_request(f'{LAMBDA_FUNCTIONS_PATH}/{id_wrong_function}', self.admin)
|
|
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
|
|
|
response = self._get_request(f'{LAMBDA_FUNCTIONS_PATH}/{id_wrong_function}', self.user)
|
|
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
|
|
|
response = self._get_request(f'{LAMBDA_FUNCTIONS_PATH}/{id_wrong_function}', None)
|
|
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
|
|
|
|
|
|
@mock.patch('cvat.apps.lambda_manager.views.LambdaGateway._http', return_value = functions["negative"][id_function_non_unique_labels])
|
|
def test_api_v2_lambda_functions_read_non_unique_labels(self, mock_http):
|
|
response = self._get_request(f'{LAMBDA_FUNCTIONS_PATH}/{id_function_non_unique_labels}', self.admin)
|
|
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
|
|
|
|
|
@skip("Fail: add mock")
|
|
def test_api_v2_lambda_requests_list(self):
|
|
response = self._get_request(LAMBDA_REQUESTS_PATH, self.admin)
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
for key in expected_keys_in_response_requests:
|
|
self.assertIn(key, response.data[0])
|
|
|
|
response = self._get_request(LAMBDA_REQUESTS_PATH, self.user)
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
for key in expected_keys_in_response_requests:
|
|
self.assertIn(key, response.data[0])
|
|
|
|
response = self._get_request(LAMBDA_REQUESTS_PATH, None)
|
|
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
|
|
|
|
|
|
def test_api_v2_lambda_requests_list_empty(self):
|
|
response = self._get_request(LAMBDA_REQUESTS_PATH, self.admin)
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
self.assertEqual(len(response.data), 0)
|
|
|
|
response = self._get_request(LAMBDA_REQUESTS_PATH, self.user)
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
self.assertEqual(len(response.data), 0)
|
|
|
|
response = self._get_request(LAMBDA_REQUESTS_PATH, None)
|
|
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
|
|
|
|
|
|
def test_api_v2_lambda_requests_read(self):
|
|
# create request
|
|
data_main_task = {
|
|
"function": id_function_detector,
|
|
"task": self.main_task["id"],
|
|
"cleanup": True,
|
|
"threshold": 55,
|
|
"quality": "original",
|
|
"mapping": {
|
|
"car": { "name": "car" },
|
|
},
|
|
}
|
|
response = self._post_request(LAMBDA_REQUESTS_PATH, self.admin, data_main_task)
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
id_request = response.data["id"]
|
|
|
|
response = self._get_request(f'{LAMBDA_REQUESTS_PATH}/{id_request}', self.admin)
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
for key in expected_keys_in_response_requests:
|
|
self.assertIn(key, response.data)
|
|
|
|
response = self._get_request(f'{LAMBDA_REQUESTS_PATH}/{id_request}', self.user)
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
for key in expected_keys_in_response_requests:
|
|
self.assertIn(key, response.data)
|
|
|
|
response = self._get_request(f'{LAMBDA_REQUESTS_PATH}/{id_request}', None)
|
|
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
|
|
|
|
|
|
def test_api_v2_lambda_requests_read_wrong_id(self):
|
|
id_request = "cf343b95-afeb-475e-ab53-8d7e64991d30-wrong-id"
|
|
|
|
response = self._get_request(f'{LAMBDA_REQUESTS_PATH}/{id_request}', self.admin)
|
|
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
|
|
|
response = self._get_request(f'{LAMBDA_REQUESTS_PATH}/{id_request}', self.user)
|
|
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
|
|
|
response = self._get_request(f'{LAMBDA_REQUESTS_PATH}/{id_request}', None)
|
|
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
|
|
|
|
|
|
def test_api_v2_lambda_requests_delete_finished_request(self):
|
|
data = {
|
|
"function": id_function_detector,
|
|
"task": self.main_task["id"],
|
|
"cleanup": True,
|
|
"mapping": {
|
|
"car": { "name": "car" },
|
|
},
|
|
}
|
|
response = self._post_request(f'{LAMBDA_REQUESTS_PATH}', self.admin, data)
|
|
id_request = response.data["id"]
|
|
|
|
response = self._delete_request(f'{LAMBDA_REQUESTS_PATH}/{id_request}', None)
|
|
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
|
|
|
|
response = self._delete_request(f'{LAMBDA_REQUESTS_PATH}/{id_request}', self.admin)
|
|
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
|
|
response = self._get_request(f'{LAMBDA_REQUESTS_PATH}/{id_request}', self.admin)
|
|
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
|
|
|
response = self._post_request(f'{LAMBDA_REQUESTS_PATH}', self.admin, data)
|
|
id_request = response.data["id"]
|
|
response = self._delete_request(f'{LAMBDA_REQUESTS_PATH}/{id_request}', self.user)
|
|
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
|
response = self._get_request(f'{LAMBDA_REQUESTS_PATH}/{id_request}', self.user)
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
|
|
|
|
@skip("Fail: add mock")
|
|
def test_api_v2_lambda_requests_delete_not_finished_request(self):
|
|
pass
|
|
|
|
|
|
def test_api_v2_lambda_requests_create(self):
|
|
ids_functions = [id_function_detector, id_function_interactor, id_function_tracker, \
|
|
id_function_reid_response_data, id_function_detector, id_function_reid_response_no_data, \
|
|
id_function_non_type, id_function_wrong_type, id_function_unknown_type]
|
|
|
|
for id_func in ids_functions:
|
|
data_main_task = {
|
|
"function": id_func,
|
|
"task": self.main_task["id"],
|
|
"cleanup": True,
|
|
"threshold": 55,
|
|
"quality": "original",
|
|
"mapping": {
|
|
"car": { "name": "car" },
|
|
},
|
|
}
|
|
data_assigneed_to_user_task = {
|
|
"function": id_func,
|
|
"task": self.assigneed_to_user_task["id"],
|
|
"cleanup": False,
|
|
"quality": "compressed",
|
|
"max_distance": 70,
|
|
"mapping": {
|
|
"car": { "name": "car" },
|
|
},
|
|
}
|
|
|
|
response = self._post_request(LAMBDA_REQUESTS_PATH, self.admin, data_main_task)
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
for key in expected_keys_in_response_requests:
|
|
self.assertIn(key, response.data)
|
|
|
|
response = self._post_request(LAMBDA_REQUESTS_PATH, self.user, data_assigneed_to_user_task)
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
for key in expected_keys_in_response_requests:
|
|
self.assertIn(key, response.data)
|
|
|
|
response = self._post_request(LAMBDA_REQUESTS_PATH, self.user, data_main_task)
|
|
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
|
|
|
response = self._post_request(LAMBDA_REQUESTS_PATH, None, data_main_task)
|
|
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
|
|
|
|
|
|
@mock.patch('cvat.apps.lambda_manager.views.LambdaGateway._http', return_value = functions["negative"]["test-model-has-non-unique-labels"])
|
|
def test_api_v2_lambda_requests_create_non_unique_labels(self, mock_http):
|
|
data = {
|
|
"function": id_function_non_unique_labels,
|
|
"task": self.main_task["id"],
|
|
"cleanup": True,
|
|
"mapping": {
|
|
"car": { "name": "car" },
|
|
},
|
|
}
|
|
|
|
response = self._post_request(LAMBDA_REQUESTS_PATH, self.admin, data)
|
|
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
|
|
|
|
|
def test_api_v2_lambda_requests_create_empty_data(self):
|
|
data = {}
|
|
response = self._post_request(LAMBDA_REQUESTS_PATH, self.admin, data)
|
|
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
def test_api_v2_lambda_requests_create_without_function(self):
|
|
data = {
|
|
"task": self.main_task["id"],
|
|
"cleanup": True,
|
|
"mapping": {
|
|
"car": { "name": "car" },
|
|
},
|
|
}
|
|
response = self._post_request(LAMBDA_REQUESTS_PATH, self.admin, data)
|
|
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
def test_api_v2_lambda_requests_create_wrong_id_function(self):
|
|
data = {
|
|
"function": "test-requests-wrong-id",
|
|
"task": self.main_task["id"],
|
|
"cleanup": True,
|
|
"mapping": {
|
|
"car": { "name": "car" },
|
|
},
|
|
}
|
|
response = self._post_request(LAMBDA_REQUESTS_PATH, self.admin, data)
|
|
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
|
|
|
|
|
@skip("Fail: add mock")
|
|
def test_api_v2_lambda_requests_create_two_requests(self):
|
|
data = {
|
|
"function": id_function_detector,
|
|
"task": self.main_task["id"],
|
|
"cleanup": True,
|
|
"mapping": {
|
|
"car": { "name": "car" },
|
|
},
|
|
}
|
|
self._post_request(LAMBDA_REQUESTS_PATH, self.admin, data)
|
|
response = self._post_request(LAMBDA_REQUESTS_PATH, self.admin, data)
|
|
self.assertEqual(response.status_code, status.HTTP_409_CONFLICT)
|
|
|
|
|
|
def test_api_v2_lambda_requests_create_empty_mapping(self):
|
|
data = {
|
|
"function": id_function_detector,
|
|
"task": self.main_task["id"],
|
|
"cleanup": True,
|
|
"mapping": {},
|
|
}
|
|
response = self._post_request(LAMBDA_REQUESTS_PATH, self.admin, data)
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
for key in expected_keys_in_response_requests:
|
|
self.assertIn(key, response.data)
|
|
|
|
|
|
def test_api_v2_lambda_requests_create_without_cleanup(self):
|
|
data = {
|
|
"function": id_function_detector,
|
|
"task": self.main_task["id"],
|
|
"mapping": {
|
|
"car": { "name": "car" },
|
|
},
|
|
}
|
|
response = self._post_request(LAMBDA_REQUESTS_PATH, self.admin, data)
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
for key in expected_keys_in_response_requests:
|
|
self.assertIn(key, response.data)
|
|
|
|
|
|
def test_api_v2_lambda_requests_create_without_mapping(self):
|
|
data = {
|
|
"function": id_function_detector,
|
|
"task": self.main_task["id"],
|
|
"cleanup": True,
|
|
}
|
|
response = self._post_request(LAMBDA_REQUESTS_PATH, self.admin, data)
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
for key in expected_keys_in_response_requests:
|
|
self.assertIn(key, response.data)
|
|
|
|
|
|
def test_api_v2_lambda_requests_create_without_task(self):
|
|
data = {
|
|
"function": id_function_detector,
|
|
"cleanup": True,
|
|
"mapping": {
|
|
"car": { "name": "car" },
|
|
},
|
|
}
|
|
response = self._post_request(LAMBDA_REQUESTS_PATH, self.admin, data)
|
|
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
def test_api_v2_lambda_requests_create_wrong_id_task(self):
|
|
data = {
|
|
"function": id_function_detector,
|
|
"task": 12345,
|
|
"cleanup": True,
|
|
"mapping": {
|
|
"car": { "name": "car" },
|
|
},
|
|
}
|
|
response = self._post_request(LAMBDA_REQUESTS_PATH, self.admin, data)
|
|
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
def test_api_v2_lambda_requests_create_is_not_ready(self):
|
|
ids_functions = [id_function_state_building, id_function_state_error]
|
|
|
|
for id_func in ids_functions:
|
|
data = {
|
|
"function": id_func,
|
|
"task": self.main_task["id"],
|
|
"cleanup": True,
|
|
"mapping": {
|
|
"car": { "name": "car" },
|
|
},
|
|
}
|
|
|
|
response = self._post_request(LAMBDA_REQUESTS_PATH, self.admin, data)
|
|
self.assertEqual(response.status_code, status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|
|
|
|
|
def test_api_v2_lambda_functions_create_detector(self):
|
|
data_main_task = {
|
|
"task": self.main_task["id"],
|
|
"frame": 0,
|
|
"cleanup": True,
|
|
"threshold": 0.55,
|
|
"mapping": {
|
|
"car": { "name": "car" },
|
|
},
|
|
}
|
|
data_assigneed_to_user_task = {
|
|
"task": self.assigneed_to_user_task["id"],
|
|
"frame": 0,
|
|
"cleanup": True,
|
|
"mapping": {
|
|
"car": { "name": "car" },
|
|
},
|
|
}
|
|
|
|
response = self._post_request(f"{LAMBDA_FUNCTIONS_PATH}/{id_function_detector}", self.admin, data_main_task)
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
|
|
response = self._post_request(f"{LAMBDA_FUNCTIONS_PATH}/{id_function_detector}", self.user, data_assigneed_to_user_task)
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
|
|
response = self._post_request(f"{LAMBDA_FUNCTIONS_PATH}/{id_function_detector}", None, data_main_task)
|
|
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
|
|
|
|
@skip("Fail: expected result != actual result") # TODO move test to test_api_v2_lambda_functions_create
|
|
def test_api_v2_lambda_functions_create_user_assigned_to_no_user(self):
|
|
data = {
|
|
"task": self.main_task["id"],
|
|
"frame": 0,
|
|
"cleanup": True,
|
|
"mapping": {
|
|
"car": { "name": "car" },
|
|
},
|
|
}
|
|
response = self._post_request(f"{LAMBDA_FUNCTIONS_PATH}/{id_function_detector}", self.user, data)
|
|
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
|
|
|
|
|
def test_api_v2_lambda_functions_create_interactor(self):
|
|
data_main_task = {
|
|
"task": self.main_task["id"],
|
|
"frame": 0,
|
|
"pos_points": [
|
|
[3.45, 6.78],
|
|
[12.1, 12.1],
|
|
[34.1, 41.0],
|
|
[43.01, 43.99],
|
|
],
|
|
"neg_points": [
|
|
[3.25, 6.58],
|
|
[11.1, 11.0],
|
|
[35.5, 44.44],
|
|
[45.01, 45.99],
|
|
],
|
|
}
|
|
data_assigneed_to_user_task = {
|
|
"task": self.assigneed_to_user_task["id"],
|
|
"frame": 0,
|
|
"threshold": 0.1,
|
|
"pos_points": [
|
|
[3.45, 6.78],
|
|
[12.1, 12.1],
|
|
[34.1, 41.0],
|
|
[43.01, 43.99],
|
|
],
|
|
"neg_points": [
|
|
[3.25, 6.58],
|
|
[11.1, 11.0],
|
|
[35.5, 44.44],
|
|
[45.01, 45.99],
|
|
],
|
|
}
|
|
|
|
response = self._post_request(f"{LAMBDA_FUNCTIONS_PATH}/{id_function_interactor}", self.admin, data_main_task)
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
|
|
response = self._post_request(f"{LAMBDA_FUNCTIONS_PATH}/{id_function_interactor}", self.user, data_assigneed_to_user_task)
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
|
|
response = self._post_request(f"{LAMBDA_FUNCTIONS_PATH}/{id_function_interactor}", None, data_main_task)
|
|
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
|
|
|
|
|
|
def test_api_v2_lambda_functions_create_tracker(self):
|
|
data_main_task = {
|
|
"task": self.main_task["id"],
|
|
"frame": 0,
|
|
"shape": [
|
|
12.12,
|
|
34.45,
|
|
54.0,
|
|
76.12,
|
|
],
|
|
}
|
|
data_assigneed_to_user_task = {
|
|
"task": self.assigneed_to_user_task["id"],
|
|
"frame": 0,
|
|
"shape": [
|
|
12.12,
|
|
34.45,
|
|
54.0,
|
|
76.12,
|
|
],
|
|
}
|
|
|
|
response = self._post_request(f"{LAMBDA_FUNCTIONS_PATH}/{id_function_tracker}", self.admin, data_main_task)
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
|
|
response = self._post_request(f"{LAMBDA_FUNCTIONS_PATH}/{id_function_tracker}", self.user, data_assigneed_to_user_task)
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
|
|
response = self._post_request(f"{LAMBDA_FUNCTIONS_PATH}/{id_function_tracker}", None, data_main_task)
|
|
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
|
|
|
|
|
|
def test_api_v2_lambda_functions_create_reid(self):
|
|
data_main_task = {
|
|
"task": self.main_task["id"],
|
|
"frame0": 0,
|
|
"frame1": 1,
|
|
"boxes0": [
|
|
OrderedDict([('attributes', []), ('frame', 0), ('group', None), ('id', 11258), ('label_id', 8), ('occluded', False), ('path_id', 0), ('points', [137.0, 129.0, 457.0, 676.0]), ('source', 'auto'), ('type', 'rectangle'), ('z_order', 0)]),
|
|
OrderedDict([('attributes', []), ('frame', 0), ('group', None), ('id', 11259), ('label_id', 8), ('occluded', False), ('path_id', 1), ('points', [1511.0, 224.0, 1537.0, 437.0]), ('source', 'auto'), ('type', 'rectangle'), ('z_order', 0)]),
|
|
],
|
|
"boxes1": [
|
|
OrderedDict([('attributes', []), ('frame', 1), ('group', None), ('id', 11260), ('label_id', 8), ('occluded', False), ('points', [1076.0, 199.0, 1218.0, 593.0]), ('source', 'auto'), ('type', 'rectangle'), ('z_order', 0)]),
|
|
OrderedDict([('attributes', []), ('frame', 1), ('group', None), ('id', 11261), ('label_id', 8), ('occluded', False), ('points', [924.0, 177.0, 1090.0, 615.0]), ('source', 'auto'), ('type', 'rectangle'), ('z_order', 0)]),
|
|
],
|
|
"quality": None,
|
|
"threshold": 0.5,
|
|
"max_distance": 55,
|
|
}
|
|
data_assigneed_to_user_task = {
|
|
"task": self.assigneed_to_user_task["id"],
|
|
"frame0": 0,
|
|
"frame1": 1,
|
|
"boxes0": [
|
|
OrderedDict([('attributes', []), ('frame', 0), ('group', None), ('id', 11258), ('label_id', 8), ('occluded', False), ('path_id', 0), ('points', [137.0, 129.0, 457.0, 676.0]), ('source', 'auto'), ('type', 'rectangle'), ('z_order', 0)]),
|
|
OrderedDict([('attributes', []), ('frame', 0), ('group', None), ('id', 11259), ('label_id', 8), ('occluded', False), ('path_id', 1), ('points', [1511.0, 224.0, 1537.0, 437.0]), ('source', 'auto'), ('type', 'rectangle'), ('z_order', 0)]),
|
|
],
|
|
"boxes1": [
|
|
OrderedDict([('attributes', []), ('frame', 1), ('group', None), ('id', 11260), ('label_id', 8), ('occluded', False), ('points', [1076.0, 199.0, 1218.0, 593.0]), ('source', 'auto'), ('type', 'rectangle'), ('z_order', 0)]),
|
|
OrderedDict([('attributes', []), ('frame', 1), ('group', 0), ('id', 11398), ('label_id', 8), ('occluded', False), ('points', [184.3935546875, 211.5048828125, 331.64968722073354, 97.27792672028772, 445.87667560321825, 126.17873100983161, 454.13404825737416, 691.8087578194827, 180.26452189455085]), ('source', 'manual'), ('type', 'polygon'), ('z_order', 0)]),
|
|
],
|
|
"quality": None,
|
|
}
|
|
|
|
response = self._post_request(f"{LAMBDA_FUNCTIONS_PATH}/{id_function_reid_response_data}", self.admin, data_main_task)
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
|
|
response = self._post_request(f"{LAMBDA_FUNCTIONS_PATH}/{id_function_reid_response_data}", self.user, data_assigneed_to_user_task)
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
|
|
response = self._post_request(f"{LAMBDA_FUNCTIONS_PATH}/{id_function_reid_response_data}", None, data_main_task)
|
|
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
|
|
|
|
response = self._post_request(f"{LAMBDA_FUNCTIONS_PATH}/{id_function_reid_response_no_data}", self.admin, data_main_task)
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
|
|
response = self._post_request(f"{LAMBDA_FUNCTIONS_PATH}/{id_function_reid_response_no_data}", self.user, data_assigneed_to_user_task)
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
|
|
response = self._post_request(f"{LAMBDA_FUNCTIONS_PATH}/{id_function_reid_response_no_data}", None, data_main_task)
|
|
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
|
|
|
|
|
|
def test_api_v2_lambda_functions_create_non_type(self):
|
|
data = {
|
|
"task": self.main_task["id"],
|
|
"frame": 0,
|
|
"cleanup": True,
|
|
"mapping": {
|
|
"car": { "name": "car" },
|
|
},
|
|
}
|
|
|
|
response = self._post_request(f"{LAMBDA_FUNCTIONS_PATH}/{id_function_non_type}", self.admin, data)
|
|
self.assertEqual(response.status_code, status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|
|
|
|
|
def test_api_v2_lambda_functions_create_wrong_type(self):
|
|
data = {
|
|
"task": self.main_task["id"],
|
|
"frame": 0,
|
|
"cleanup": True,
|
|
"mapping": {
|
|
"car": { "name": "car" },
|
|
},
|
|
}
|
|
|
|
response = self._post_request(f"{LAMBDA_FUNCTIONS_PATH}/{id_function_wrong_type}", self.admin, data)
|
|
self.assertEqual(response.status_code, status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|
|
|
|
|
def test_api_v2_lambda_functions_create_unknown_type(self):
|
|
data = {
|
|
"task": self.main_task["id"],
|
|
"frame": 0,
|
|
"cleanup": True,
|
|
"mapping": {
|
|
"car": { "name": "car" },
|
|
},
|
|
}
|
|
|
|
response = self._post_request(f"{LAMBDA_FUNCTIONS_PATH}/{id_function_unknown_type}", self.admin, data)
|
|
self.assertEqual(response.status_code, status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|
|
|
|
|
@mock.patch('cvat.apps.lambda_manager.views.LambdaGateway._http', return_value = functions["negative"]["test-model-has-non-unique-labels"])
|
|
def test_api_v2_lambda_functions_create_non_unique_labels(self, mock_http):
|
|
data = {
|
|
"task": self.main_task["id"],
|
|
"frame": 0,
|
|
"cleanup": True,
|
|
"mapping": {
|
|
"car": { "name": "car" },
|
|
},
|
|
}
|
|
|
|
response = self._post_request(f"{LAMBDA_FUNCTIONS_PATH}/{id_function_non_unique_labels}", self.admin, data)
|
|
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
|
|
|
|
|
def test_api_v2_lambda_functions_create_quality(self):
|
|
qualities = [None, "original", "compressed"]
|
|
|
|
for quality in qualities:
|
|
data = {
|
|
"task": self.main_task["id"],
|
|
"frame": 0,
|
|
"cleanup": True,
|
|
"quality": quality,
|
|
"mapping": {
|
|
"car": { "name": "car" },
|
|
},
|
|
}
|
|
|
|
response = self._post_request(f"{LAMBDA_FUNCTIONS_PATH}/{id_function_detector}", self.admin, data)
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
|
|
data = {
|
|
"task": self.main_task["id"],
|
|
"frame": 0,
|
|
"cleanup": True,
|
|
"quality": "test-error-quality",
|
|
"mapping": {
|
|
"car": { "name": "car" },
|
|
},
|
|
}
|
|
|
|
response = self._post_request(f"{LAMBDA_FUNCTIONS_PATH}/{id_function_detector}", self.admin, data)
|
|
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
def test_api_v2_lambda_functions_create_empty_data(self):
|
|
data = {}
|
|
response = self._post_request(f"{LAMBDA_FUNCTIONS_PATH}/{id_function_detector}", self.admin, data)
|
|
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
def test_api_v2_lambda_functions_create_detector_empty_mapping(self):
|
|
data = {
|
|
"task": self.main_task["id"],
|
|
"frame": 0,
|
|
"cleanup": True,
|
|
"mapping": {},
|
|
}
|
|
response = self._post_request(f"{LAMBDA_FUNCTIONS_PATH}/{id_function_detector}", self.admin, data)
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
|
|
|
|
def test_api_v2_lambda_functions_create_detector_without_cleanup(self):
|
|
data = {
|
|
"task": self.main_task["id"],
|
|
"frame": 0,
|
|
"mapping": {
|
|
"car": { "name": "car" },
|
|
},
|
|
}
|
|
response = self._post_request(f"{LAMBDA_FUNCTIONS_PATH}/{id_function_detector}", self.admin, data)
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
|
|
|
|
def test_api_v2_lambda_functions_create_detector_without_mapping(self):
|
|
data = {
|
|
"task": self.main_task["id"],
|
|
"frame": 0,
|
|
"cleanup": True,
|
|
}
|
|
response = self._post_request(f"{LAMBDA_FUNCTIONS_PATH}/{id_function_detector}", self.admin, data)
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
|
|
|
|
def test_api_v2_lambda_functions_create_detector_without_task(self):
|
|
data = {
|
|
"frame": 0,
|
|
"cleanup": True,
|
|
"mapping": {
|
|
"car": { "name": "car" },
|
|
},
|
|
}
|
|
response = self._post_request(f"{LAMBDA_FUNCTIONS_PATH}/{id_function_detector}", self.admin, data)
|
|
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
def test_api_v2_lambda_functions_create_detector_without_id_frame(self):
|
|
data = {
|
|
"task": self.main_task["id"],
|
|
"cleanup": True,
|
|
"mapping": {
|
|
"car": { "name": "car" },
|
|
},
|
|
}
|
|
response = self._post_request(f"{LAMBDA_FUNCTIONS_PATH}/{id_function_detector}", self.admin, data)
|
|
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
def test_api_v2_lambda_functions_create_wrong_id_function(self):
|
|
data = {
|
|
"task": self.main_task["id"],
|
|
"frame": 0,
|
|
"cleanup": True,
|
|
"mapping": {
|
|
"car": { "name": "car" },
|
|
},
|
|
}
|
|
response = self._post_request(f"{LAMBDA_FUNCTIONS_PATH}/test-functions-wrong-id", self.admin, data)
|
|
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
|
|
|
|
|
def test_api_v2_lambda_functions_create_wrong_id_task(self):
|
|
data = {
|
|
"task": 12345,
|
|
"frame": 0,
|
|
"cleanup": True,
|
|
"mapping": {
|
|
"car": { "name": "car" },
|
|
},
|
|
}
|
|
response = self._post_request(f"{LAMBDA_FUNCTIONS_PATH}/{id_function_detector}", self.admin, data)
|
|
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
@skip("Fail: expected result != actual result, issue #2770")
|
|
def test_api_v2_lambda_functions_create_detector_wrong_id_frame(self):
|
|
data = {
|
|
"task": self.main_task["id"],
|
|
"frame": 12345,
|
|
"cleanup": True,
|
|
"mapping": {
|
|
"car": { "name": "car" },
|
|
},
|
|
}
|
|
response = self._post_request(f"{LAMBDA_FUNCTIONS_PATH}/{id_function_detector}", self.admin, data)
|
|
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
@skip("Fail: add mock and expected result != actual result")
|
|
def test_api_v2_lambda_functions_create_two_functions(self):
|
|
data = {
|
|
"task": self.main_task["id"],
|
|
"frame": 0,
|
|
"cleanup": True,
|
|
"mapping": {
|
|
"car": { "name": "car" },
|
|
},
|
|
}
|
|
self._post_request(f"{LAMBDA_FUNCTIONS_PATH}/{id_function_detector}", self.admin, data)
|
|
response = self._post_request(f"{LAMBDA_FUNCTIONS_PATH}/{id_function_detector}", self.admin, data)
|
|
self.assertEqual(response.status_code, status.HTTP_409_CONFLICT)
|
|
|
|
|
|
def test_api_v2_lambda_functions_create_function_is_not_ready(self):
|
|
data = {
|
|
"task": self.main_task["id"],
|
|
"frame": 0,
|
|
"cleanup": True,
|
|
"mapping": {
|
|
"car": { "name": "car" },
|
|
},
|
|
}
|
|
response = self._post_request(f"{LAMBDA_FUNCTIONS_PATH}/{id_function_state_building}", self.admin, data)
|
|
self.assertEqual(response.status_code, status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|
|
|
response = self._post_request(f"{LAMBDA_FUNCTIONS_PATH}/{id_function_state_error}", self.admin, data)
|
|
self.assertEqual(response.status_code, status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|
|
|
|
|
class Issue4996_Cases(_LambdaTestCaseBase):
|
|
# Check regressions for https://github.com/opencv/cvat/issues/4996#issuecomment-1266123032
|
|
# We need to check that job assignee can call functions in the assigned jobs
|
|
# This requires to pass the job id in the call request.
|
|
|
|
def _create_org(self, *, owner: int, members: Dict[int, str] = None) -> dict:
|
|
org = self._post_request('/api/organizations', user=owner, data={
|
|
"slug": "testorg",
|
|
"name": "test Org",
|
|
})
|
|
assert org.status_code == status.HTTP_201_CREATED
|
|
org = org.json()
|
|
|
|
for uid, role in members.items():
|
|
user = self._get_request('/api/users/self', user=uid)
|
|
assert user.status_code == status.HTTP_200_OK
|
|
user = user.json()
|
|
|
|
invitation = self._post_request('/api/invitations', user=owner, data={
|
|
'email': user['email'],
|
|
'role': role,
|
|
}, org_id=org['id'])
|
|
assert invitation.status_code == status.HTTP_201_CREATED
|
|
|
|
return org
|
|
|
|
def _set_task_assignee(self, task: int, assignee: Optional[int], *,
|
|
org_id: Optional[int] = None):
|
|
response = self._patch_request(f'/api/tasks/{task}', user=self.admin, data={
|
|
'assignee_id': assignee,
|
|
}, org_id=org_id)
|
|
assert response.status_code == status.HTTP_200_OK
|
|
|
|
def _set_job_assignee(self, job: int, assignee: Optional[int], *,
|
|
org_id: Optional[int] = None):
|
|
response = self._patch_request(f'/api/jobs/{job}', user=self.admin, data={
|
|
'assignee': assignee,
|
|
}, org_id=org_id)
|
|
assert response.status_code == status.HTTP_200_OK
|
|
|
|
def setUp(self):
|
|
self.org = self._create_org(owner=self.admin, members={self.user: 'worker'})
|
|
|
|
task = self._create_task(data={
|
|
'name': 'test_task',
|
|
'labels': [{'name': 'cat'}],
|
|
'segment_size': 2
|
|
},
|
|
image_data=self._generate_task_images(6),
|
|
owner=self.admin,
|
|
org_id=self.org['id'],
|
|
)
|
|
self.task = task
|
|
|
|
jobs = get_paginated_collection(lambda page:
|
|
self._get_request(
|
|
f"/api/tasks/{self.task['id']}/jobs?page={page}",
|
|
self.admin, org_id=self.org['id']
|
|
)
|
|
)
|
|
self.job = jobs[1]
|
|
|
|
self.common_data = {
|
|
"task": self.task['id'],
|
|
"frame": 0,
|
|
"cleanup": True,
|
|
"mapping": {
|
|
"car": { "name": "car" },
|
|
},
|
|
}
|
|
|
|
self.function_name = f"{LAMBDA_FUNCTIONS_PATH}/{id_function_detector}"
|
|
|
|
return super().setUp()
|
|
|
|
def _get_valid_job_params(self):
|
|
return {
|
|
"job": self.job['id'],
|
|
"frame": 2
|
|
}
|
|
|
|
def _get_invalid_job_params(self):
|
|
return {
|
|
"job": self.job['id'],
|
|
"frame": 0
|
|
}
|
|
|
|
def test_can_call_function_for_job_worker_in_org__deny_unassigned_worker_with_task_request(self):
|
|
data = self.common_data.copy()
|
|
with self.subTest(job=None, assignee=None):
|
|
response = self._post_request(self.function_name, self.user, data,
|
|
org_id=self.org['id'])
|
|
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
|
|
|
def test_can_call_function_for_job_worker_in_org__deny_unassigned_worker_with_job_request(self):
|
|
data = self.common_data.copy()
|
|
data.update(self._get_valid_job_params())
|
|
with self.subTest(job='defined', assignee=None):
|
|
response = self._post_request(self.function_name, self.user, data,
|
|
org_id=self.org['id'])
|
|
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
|
|
|
def test_can_call_function_for_job_worker_in_org__allow_task_assigned_worker_with_task_request(self):
|
|
self._set_task_assignee(self.task['id'], self.user.id, org_id=self.org['id'])
|
|
|
|
data = self.common_data.copy()
|
|
with self.subTest(job=None, assignee='task'):
|
|
response = self._post_request(self.function_name, self.user, data,
|
|
org_id=self.org['id'])
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
|
|
def test_can_call_function_for_job_worker_in_org__deny_job_assigned_worker_with_task_request(self):
|
|
self._set_job_assignee(self.job['id'], self.user.id, org_id=self.org['id'])
|
|
|
|
data = self.common_data.copy()
|
|
with self.subTest(job=None, assignee='job'):
|
|
response = self._post_request(self.function_name, self.user, data,
|
|
org_id=self.org['id'])
|
|
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
|
|
|
def test_can_call_function_for_job_worker_in_org__allow_job_assigned_worker_with_job_request(self):
|
|
self._set_job_assignee(self.job['id'], self.user.id, org_id=self.org['id'])
|
|
|
|
data = self.common_data.copy()
|
|
data.update(self._get_valid_job_params())
|
|
with self.subTest(job='defined', assignee='job'):
|
|
response = self._post_request(self.function_name, self.user, data,
|
|
org_id=self.org['id'])
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
|
|
def test_can_check_job_boundaries_in_function_call__fail_for_frame_outside_job(self):
|
|
self._set_job_assignee(self.job['id'], self.user.id, org_id=self.org['id'])
|
|
|
|
data = self.common_data.copy()
|
|
data.update(self._get_invalid_job_params())
|
|
with self.subTest(job='defined', frame='outside'):
|
|
response = self._post_request(self.function_name, self.user, data,
|
|
org_id=self.org['id'])
|
|
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
|
|
|
def test_can_check_job_boundaries_in_function_call__ok_for_frame_inside_job(self):
|
|
self._set_job_assignee(self.job['id'], self.user.id, org_id=self.org['id'])
|
|
|
|
data = self.common_data.copy()
|
|
data.update(self._get_valid_job_params())
|
|
with self.subTest(job='defined', frame='inside'):
|
|
response = self._post_request(self.function_name, self.user, data,
|
|
org_id=self.org['id'])
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|