clearml-server/server/tests/automated/test_models.py
allegroai baba8b5b73 Move to ElasticSearch 7
Add initial support for project ordering
Add support for sortable task duration (used by the UI in the experiment's table)
Add support for project name in worker's current task info
Add support for results and artifacts in pre-populates examples
Add demo server features
2020-08-10 08:30:40 +03:00

278 lines
9.9 KiB
Python

from apierrors.errors.bad_request import InvalidModelId
from tests.automated import TestService
MODEL_CANNOT_BE_UPDATED_CODES = (400, 203)
TASK_CANNOT_BE_UPDATED_CODES = (400, 110)
PUBLISHED = "published"
IN_PROGRESS = "in_progress"
class TestModelsService(TestService):
def setUp(self, version="2.9"):
super().setUp(version=version)
def test_publish_output_model_running_task(self):
task_id, model_id = self._create_task_and_model()
self._assert_model_ready(model_id, False)
with self._assert_update_task_failure():
self.api.models.set_ready(model=model_id)
self._assert_model_ready(model_id, False)
self._assert_task_status(task_id, IN_PROGRESS)
def test_publish_output_model_running_task_no_task_publish(self):
task_id, model_id = self._create_task_and_model()
self._assert_model_ready(model_id, False)
res = self.api.models.set_ready(model=model_id, publish_task=False)
assert res.updated == 1 # model updated
assert res.get("published_task", None) is None
self._assert_model_ready(model_id, True)
self._assert_task_status(task_id, IN_PROGRESS)
def test_publish_output_model_running_task_force_task_publish(self):
task_id, model_id = self._create_task_and_model()
self._assert_model_ready(model_id, False)
self.api.models.set_ready(model=model_id, force_publish_task=True)
self._assert_model_ready(model_id, True)
self._assert_task_status(task_id, PUBLISHED)
def test_publish_output_model_published_task(self):
task_id, model_id = self._create_task_and_model()
self._assert_model_ready(model_id, False)
self.api.tasks.stopped(task=task_id)
self.api.tasks.publish(task=task_id, publish_model=False)
self._assert_model_ready(model_id, False)
self._assert_task_status(task_id, PUBLISHED)
res = self.api.models.set_ready(model=model_id)
assert res.updated == 1 # model updated
assert res.get("published_task", None) is None
self._assert_model_ready(model_id, True)
self._assert_task_status(task_id, PUBLISHED)
def test_publish_output_model_stopped_task(self):
task_id, model_id = self._create_task_and_model()
self._assert_model_ready(model_id, False)
self.api.tasks.stopped(task=task_id)
res = self.api.models.set_ready(model=model_id)
assert res.updated == 1 # model updated
assert res.published_task.id == task_id
assert res.published_task.data.updated == 1
self._assert_model_ready(model_id, True)
self._assert_task_status(task_id, PUBLISHED)
# cannot publish already published model
with self._assert_update_model_failure():
self.api.models.set_ready(model=model_id)
self._assert_model_ready(model_id, True)
def test_publish_output_model_no_task(self):
model_id = self.create_temp(
service="models", name='test', uri='file:///a', labels={}, ready=False
)
self._assert_model_ready(model_id, False)
res = self.api.models.set_ready(model=model_id)
assert res.updated == 1 # model updated
assert res.get("task", None) is None
self._assert_model_ready(model_id, True)
def test_publish_task_with_output_model(self):
task_id, model_id = self._create_task_and_model()
self._assert_model_ready(model_id, False)
self.api.tasks.stopped(task=task_id)
res = self.api.tasks.publish(task=task_id)
assert res.updated == 1 # model updated
self._assert_model_ready(model_id, True)
self._assert_task_status(task_id, PUBLISHED)
def test_publish_task_with_published_model(self):
task_id, model_id = self._create_task_and_model()
self.api.models.set_ready(model=model_id, publish_task=False)
self._assert_model_ready(model_id, True)
self.api.tasks.stopped(task=task_id)
res = self.api.tasks.publish(task=task_id)
assert res.updated == 1 # model updated
self._assert_task_status(task_id, PUBLISHED)
self._assert_model_ready(model_id, True)
def test_publish_task_no_output_model(self):
task_id = self.create_temp(
service="tasks", type='testing', name='server-test', input=dict(view={})
)
self.api.tasks.started(task=task_id)
self.api.tasks.stopped(task=task_id)
res = self.api.tasks.publish(task=task_id)
assert res.updated == 1 # model updated
self._assert_task_status(task_id, PUBLISHED)
def test_update_model_iteration_with_task(self):
task_id = self._create_task()
model_id = self._create_model()
self.api.models.update(model=model_id, task=task_id, iteration=1000, labels={"foo": 1})
self.assertEqual(
self.api.tasks.get_by_id(task=task_id).task.last_iteration,
1000
)
self.api.models.update(model=model_id, task=task_id, iteration=500)
self.assertEqual(
self.api.tasks.get_by_id(task=task_id).task.last_iteration,
1000
)
def test_update_model_for_task_iteration(self):
task_id = self._create_task()
res = self.api.models.update_for_task(
task=task_id,
name="test model",
uri="file:///b",
iteration=999,
)
model_id = res.id
self.defer(self.api.models.delete, can_fail=True, model=model_id, force=True)
self.assertEqual(
self.api.tasks.get_by_id(task=task_id).task.last_iteration,
999
)
self.api.models.update_for_task(task=task_id, uri="file:///c", iteration=1000)
self.assertEqual(
self.api.tasks.get_by_id(task=task_id).task.last_iteration,
1000
)
self.api.models.update_for_task(task=task_id, uri="file:///d", iteration=888)
self.assertEqual(
self.api.tasks.get_by_id(task=task_id).task.last_iteration,
1000
)
def test_get_frameworks(self):
framework_1 = "Test framework 1"
framework_2 = "Test framework 2"
# create model on top level
self._create_model(name="framework model test", framework=framework_1)
# create model under a project as make it inherit its framework from the task
project = self.create_temp("projects", name="Frameworks test", description="")
task = self._create_task(project=project, execution=dict(framework=framework_2))
self.api.models.update_for_task(
task=task,
name="framework output model test",
uri="file:///b",
iteration=999,
)
# get all frameworks
res = self.api.models.get_frameworks()
self.assertTrue({framework_1, framework_2}.issubset(set(res.frameworks)))
# get frameworks under the project
res = self.api.models.get_frameworks(projects=[project])
self.assertEqual([framework_2], res.frameworks)
# empty result
self.api.tasks.delete(task=task, force=True)
res = self.api.models.get_frameworks(projects=[project])
self.assertEqual([], res.frameworks)
def test_make_public(self):
m1 = self._create_model(name="public model test")
# model with company_origin not set to the current company cannot be converted to private
with self.api.raises(InvalidModelId):
self.api.models.make_private(ids=[m1])
# public model can be retrieved but not updated
res = self.api.models.make_public(ids=[m1])
self.assertEqual(res.updated, 1)
res = self.api.models.get_all(id=[m1])
self.assertEqual([m.id for m in res.models], [m1])
with self.api.raises(InvalidModelId):
self.api.models.update(model=m1, name="public model test change 1")
# task made private again and can be both retrieved and updated
res = self.api.models.make_private(ids=[m1])
self.assertEqual(res.updated, 1)
res = self.api.models.get_all(id=[m1])
self.assertEqual([m.id for m in res.models], [m1])
self.api.models.update(model=m1, name="public model test change 2")
def _assert_task_status(self, task_id, status):
task = self.api.tasks.get_by_id(task=task_id).task
assert task.status == status
def _assert_model_ready(self, model_id, ready):
model = self.api.models.get_by_id(model=model_id)["model"]
assert model.ready == ready
def _assert_update_model_failure(self):
return self.api.raises(MODEL_CANNOT_BE_UPDATED_CODES)
def _assert_update_task_failure(self):
return self.api.raises(TASK_CANNOT_BE_UPDATED_CODES)
def _create_model(self, **kwargs):
return self.create_temp(
service="models",
delete_params=dict(can_fail=True, force=True),
name=kwargs.pop("name", 'test'),
uri=kwargs.pop("name", 'file:///a'),
labels=kwargs.pop("labels", {}),
**kwargs,
)
def _create_task(self, **kwargs):
task_id = self.create_temp(
service="tasks",
type=kwargs.pop("type", 'testing'),
name=kwargs.pop("name", 'server-test'),
input=kwargs.pop("input", dict(view={})),
**kwargs,
)
return task_id
def _create_task_and_model(self):
execution_model_id = self.create_temp(
service="models",
name='test',
uri='file:///a',
labels={}
)
task_id = self.create_temp(
service="tasks",
type='testing',
name='server-test',
input=dict(view={}),
execution=dict(model=execution_model_id)
)
self.api.tasks.started(task=task_id)
output_model_id = self.api.models.update_for_task(
task=task_id, uri='file:///b'
)["id"]
return task_id, output_model_id