diff --git a/.gitattributes b/.gitattributes index cbad3e19803df0a29ca8a7e578b34041e1b38ab9..ab6138a84b112dd569695fd31e1fc1b4d52e3131 100644 --- a/.gitattributes +++ b/.gitattributes @@ -4245,7 +4245,7 @@ SAS/LSMR/src/lsmr/lsmrapp/__init__.py -text SAS/LSMR/src/lsmr/lsmrapp/admin.py -text SAS/LSMR/src/lsmr/lsmrapp/apps.py -text SAS/LSMR/src/lsmr/lsmrapp/migrations/0001_initial.py -text -SAS/LSMR/src/lsmr/lsmrapp/migrations/0002_auto_20180910_0928.py -text +SAS/LSMR/src/lsmr/lsmrapp/migrations/0002_auto_20180913_1612.py -text SAS/LSMR/src/lsmr/lsmrapp/migrations/0003_populate.py -text SAS/LSMR/src/lsmr/lsmrapp/migrations/CMakeLists.txt -text SAS/LSMR/src/lsmr/lsmrapp/migrations/__init__.py -text diff --git a/SAS/LSMR/src/lsmr/lsmrapp/migrations/0002_auto_20180910_0928.py b/SAS/LSMR/src/lsmr/lsmrapp/migrations/0002_auto_20180913_1612.py similarity index 97% rename from SAS/LSMR/src/lsmr/lsmrapp/migrations/0002_auto_20180910_0928.py rename to SAS/LSMR/src/lsmr/lsmrapp/migrations/0002_auto_20180913_1612.py index 88cd23559a13e2a86f17341ec9c8f0a7d4367077..5689c9289277d7e1a522576e5d3220ded764217b 100644 --- a/SAS/LSMR/src/lsmr/lsmrapp/migrations/0002_auto_20180910_0928.py +++ b/SAS/LSMR/src/lsmr/lsmrapp/migrations/0002_auto_20180913_1612.py @@ -1,4 +1,4 @@ -# Generated by Django 2.0.6 on 2018-09-10 09:28 +# Generated by Django 2.0.6 on 2018-09-13 16:12 import django.contrib.postgres.fields import django.contrib.postgres.fields.jsonb @@ -77,7 +77,7 @@ class Migration(migrations.Migration): ('deleted_since', models.DateTimeField(null=True)), ('pinned_since', models.DateTimeField(null=True)), ('specification', django.contrib.postgres.fields.jsonb.JSONField()), - ('dataformat', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='lsmrapp.DataformatChoice')), + ('dataformat', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.DataformatChoice')), ], options={ 'abstract': False, @@ -229,7 +229,7 @@ class Migration(migrations.Migration): ('priority', models.IntegerField(default=0)), ('can_trigger', models.BooleanField(default=False)), ('private_data', models.BooleanField(default=True)), - ('cycle', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='projects', to='lsmrapp.Cycle')), + ('cycle', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='projects', to='lsmrapp.Cycle')), ], options={ 'abstract': False, @@ -272,7 +272,7 @@ class Migration(migrations.Migration): ('requirements_doc', django.contrib.postgres.fields.jsonb.JSONField()), ('generator_param', models.CharField(max_length=200)), ('copies', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='copied_from', to='lsmrapp.RunDraft')), - ('copy_reason', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='lsmrapp.CopyReasonChoice')), + ('copy_reason', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.CopyReasonChoice')), ], options={ 'abstract': False, @@ -289,7 +289,7 @@ class Migration(migrations.Migration): ('description', models.CharField(max_length=255)), ('generator_parameters_doc', django.contrib.postgres.fields.jsonb.JSONField()), ('generator_template', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='lsmrapp.GeneratorTemplate')), - ('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='run_sets', to='lsmrapp.Project')), + ('project', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='run_sets', to='lsmrapp.Project')), ], options={ 'abstract': False, @@ -351,7 +351,7 @@ class Migration(migrations.Migration): ('created_at', models.DateTimeField(auto_now_add=True)), ('updated_at', models.DateTimeField(auto_now=True)), ('dataformats', models.ManyToManyField(blank=True, to='lsmrapp.DataformatChoice')), - ('datatype', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='lsmrapp.DatatypeChoice')), + ('datatype', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.DatatypeChoice')), ], options={ 'abstract': False, @@ -401,7 +401,7 @@ class Migration(migrations.Migration): ('created_at', models.DateTimeField(auto_now_add=True)), ('updated_at', models.DateTimeField(auto_now=True)), ('dataformats', models.ManyToManyField(blank=True, to='lsmrapp.DataformatChoice')), - ('datatype', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='lsmrapp.DatatypeChoice')), + ('datatype', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.DatatypeChoice')), ], options={ 'abstract': False, @@ -450,7 +450,7 @@ class Migration(migrations.Migration): ('description', models.CharField(max_length=255)), ('requirements_doc', django.contrib.postgres.fields.jsonb.JSONField()), ('copies', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='copied_from', to='lsmrapp.WorkRequestDraft')), - ('copy_reason', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='lsmrapp.CopyReasonChoice')), + ('copy_reason', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.CopyReasonChoice')), ('run_draft', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='lsmrapp.RunDraft')), ], options={ @@ -466,7 +466,7 @@ class Migration(migrations.Migration): ('updated_at', models.DateTimeField(auto_now=True)), ('selection_doc', django.contrib.postgres.fields.jsonb.JSONField()), ('consumer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='consumed_by', to='lsmrapp.WorkRequestBlueprint')), - ('dataformat', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='lsmrapp.DataformatChoice')), + ('dataformat', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.DataformatChoice')), ], options={ 'abstract': False, @@ -481,7 +481,7 @@ class Migration(migrations.Migration): ('updated_at', models.DateTimeField(auto_now=True)), ('selection_doc', django.contrib.postgres.fields.jsonb.JSONField()), ('consumer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='consumed_by', to='lsmrapp.WorkRequestDraft')), - ('dataformat', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='lsmrapp.DataformatChoice')), + ('dataformat', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.DataformatChoice')), ('input_role', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='inputs_work_request_relation_draft', to='lsmrapp.WorkIORole')), ('output_role', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='outputs_work_request_relation_draft', to='lsmrapp.WorkIORole')), ('producer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='produced_by', to='lsmrapp.WorkRequestDraft')), @@ -566,7 +566,7 @@ class Migration(migrations.Migration): migrations.AddField( model_name='workiorole', name='role', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='lsmrapp.RoleChoice'), + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.RoleChoice'), ), migrations.AddField( model_name='taskiorole', @@ -581,7 +581,7 @@ class Migration(migrations.Migration): migrations.AddField( model_name='taskiorole', name='role', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='lsmrapp.RoleChoice'), + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.RoleChoice'), ), migrations.AddField( model_name='task', @@ -596,12 +596,12 @@ class Migration(migrations.Migration): migrations.AddField( model_name='task', name='template', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='lsmrapp.TaskTemplate'), + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.TaskTemplate'), ), migrations.AddField( model_name='task', name='type', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='lsmrapp.TaskTypeChoice'), + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.TaskTypeChoice'), ), migrations.AddField( model_name='task', @@ -686,7 +686,7 @@ class Migration(migrations.Migration): migrations.AddField( model_name='antennaset', name='station_type', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='lsmrapp.StationTypeChoice'), + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='lsmrapp.StationTypeChoice'), ), migrations.AddIndex( model_name='workrequestrelationdraft', diff --git a/SAS/LSMR/src/lsmr/lsmrapp/migrations/0003_populate.py b/SAS/LSMR/src/lsmr/lsmrapp/migrations/0003_populate.py index 9ae51284cc81835cdeb25d396332d8afcbec9da5..2510d1b287f97b6c43e2bdd21805b114de62d800 100644 --- a/SAS/LSMR/src/lsmr/lsmrapp/migrations/0003_populate.py +++ b/SAS/LSMR/src/lsmr/lsmrapp/migrations/0003_populate.py @@ -6,7 +6,7 @@ from ..populate import * class Migration(migrations.Migration): dependencies = [ - ('lsmrapp', '0002_auto_20180910_0928'), + ('lsmrapp', '0002_auto_20180913_1612'), ] operations = [ migrations.RunPython(populate_choices) ] diff --git a/SAS/LSMR/src/lsmr/lsmrapp/models/scheduling.py b/SAS/LSMR/src/lsmr/lsmrapp/models/scheduling.py index 2639aa1bb2aa2ceff967a30d37b761bbed62b7ca..8ab71de6be79dcbc01118030cda92c9747351a77 100644 --- a/SAS/LSMR/src/lsmr/lsmrapp/models/scheduling.py +++ b/SAS/LSMR/src/lsmr/lsmrapp/models/scheduling.py @@ -14,8 +14,8 @@ from enum import Enum # class TaskIORole(BasicCommon): - role = ForeignKey('RoleChoice', null=False, on_delete=CASCADE) - datatype = ForeignKey('DatatypeChoice', null=False, on_delete=CASCADE) + role = ForeignKey('RoleChoice', null=False, on_delete=PROTECT) + datatype = ForeignKey('DatatypeChoice', null=False, on_delete=PROTECT) dataformats = ManyToManyField('DataformatChoice', blank=True) outputs = ManyToManyField('TaskTemplate', related_name='inputs_dataproduct_relation', blank=True) # blank=True required to make ManyToMany optional in Django validation inputs = ManyToManyField('TaskTemplate', related_name='input_roles_dataproduct_relation', blank=True) @@ -93,15 +93,15 @@ class DefaultDataproductSpecificationTemplate(BasicCommon): # class Task(BasicCommon): - type = ForeignKey('TaskTypeChoice', null=False, on_delete=CASCADE) + type = ForeignKey('TaskTypeChoice', null=False, on_delete=PROTECT) start_time = DateTimeField() stop_time = DateTimeField() - state = ForeignKey('TaskStateChoice', null=False, on_delete=PROTECT, related_name='task_states') # set CANCELLED or ERROR instead? - requested_state = ForeignKey('TaskStateChoice', null=False, on_delete=PROTECT, related_name='task_requested_states') # set CANCELLED or ERROR instead? + state = ForeignKey('TaskStateChoice', null=False, on_delete=PROTECT, related_name='task_states') + requested_state = ForeignKey('TaskStateChoice', null=False, on_delete=PROTECT, related_name='task_requested_states') specification = JSONField() work_request_blueprint = ForeignKey('WorkRequestBlueprint', null=True, on_delete=SET_NULL) - template = ForeignKey('TaskTemplate', null=False, on_delete=CASCADE) - # resource_claim = ForeignKey("ResourceClaim", null=False, on_delete=CASCADE) # todo <-- how is this external reference supposed to work? + template = ForeignKey('TaskTemplate', null=False, on_delete=PROTECT) + # resource_claim = ForeignKey("ResourceClaim", null=False, on_delete=PROTECT) # todo <-- how is this external reference supposed to work? class DataproductRelation(BasicCommon): @@ -115,7 +115,7 @@ class DataproductRelation(BasicCommon): class Dataproduct(BasicCommon): filename = CharField(max_length=128) directory = CharField(max_length=1024) - dataformat = ForeignKey('DataformatChoice', null=False, on_delete=CASCADE) + dataformat = ForeignKey('DataformatChoice', null=False, on_delete=PROTECT) deleted_since = DateTimeField(null=True) pinned_since = DateTimeField(null=True) specification = JSONField() @@ -123,6 +123,6 @@ class Dataproduct(BasicCommon): class AntennaSet(NamedCommon): - station_type = ForeignKey('StationTypeChoice', null=False, on_delete=CASCADE) + station_type = ForeignKey('StationTypeChoice', null=False, on_delete=PROTECT) rcus = ArrayField(IntegerField(), size=128, blank=False) inputs = ArrayField(CharField(max_length=30), size=128, blank=True) diff --git a/SAS/LSMR/src/lsmr/lsmrapp/models/specification.py b/SAS/LSMR/src/lsmr/lsmrapp/models/specification.py index bf634a919787aa944029f9fbd4f69abf9843f451..d65be6704dbb944d7aba30e381c648e7b2a53ee6 100644 --- a/SAS/LSMR/src/lsmr/lsmrapp/models/specification.py +++ b/SAS/LSMR/src/lsmr/lsmrapp/models/specification.py @@ -120,8 +120,8 @@ class CopyReasonChoice(AbstractChoice): # concrete models class WorkIORole(BasicCommon): - role = ForeignKey('RoleChoice', null=False, on_delete=CASCADE) - datatype = ForeignKey('DatatypeChoice', null=False, on_delete=CASCADE) + role = ForeignKey('RoleChoice', null=False, on_delete=PROTECT) + datatype = ForeignKey('DatatypeChoice', null=False, on_delete=PROTECT) dataformats = ManyToManyField('DataformatChoice', blank=True) outputs = ForeignKey("WorkRequestTemplate", related_name='role_output', on_delete=CASCADE) inputs = ForeignKey("WorkRequestTemplate", related_name='role_input', on_delete=CASCADE) @@ -188,7 +188,8 @@ class Cycle(NamedCommon): class Project(NamedCommon): - cycle = ForeignKey('Cycle', related_name='projects', on_delete=SET_NULL, null=True) + # cycle is protected since we have to manually decide to clean up projects with a cycle or keep them without cycle + cycle = ForeignKey('Cycle', related_name='projects', on_delete=PROTECT, null=True) priority = IntegerField(default=0) # todo: define a value for the default priority can_trigger = BooleanField(default=False) private_data = BooleanField(default=True) @@ -197,13 +198,13 @@ class Project(NamedCommon): class RunSet(NamedCommon): generator_parameters_doc = JSONField() generator_template = ForeignKey('GeneratorTemplate', on_delete=SET_NULL, null=True) - project = ForeignKey('Project', related_name="run_sets", on_delete=CASCADE) + project = ForeignKey('Project', related_name="run_sets", on_delete=PROTECT) # protected to avoid accidents class RunDraft(NamedCommon): requirements_doc = JSONField() copies = ForeignKey('RunDraft', related_name="copied_from", on_delete=SET_NULL, null=True) - copy_reason = ForeignKey('CopyReasonChoice', null=False, on_delete=CASCADE) + copy_reason = ForeignKey('CopyReasonChoice', null=False, on_delete=PROTECT) generator_param = CharField(max_length=200) # todo: check if the field size is good enough run_set = ForeignKey(RunSet, related_name='run_drafts', on_delete=CASCADE) generator_source = ForeignKey(RunSet, on_delete=SET_NULL, null=True) @@ -220,7 +221,7 @@ class RunBlueprint(NamedCommon): class WorkRequestDraft(NamedCommon): requirements_doc = JSONField() copies = ForeignKey('WorkRequestDraft', related_name="copied_from", on_delete=SET_NULL, null=True) - copy_reason = ForeignKey('CopyReasonChoice', null=False, on_delete=CASCADE) + copy_reason = ForeignKey('CopyReasonChoice', null=False, on_delete=PROTECT) run_draft = ForeignKey(RunDraft, on_delete=CASCADE) template = ForeignKey('WorkRequestTemplate', on_delete=CASCADE) @@ -235,7 +236,7 @@ class WorkRequestBlueprint(NamedCommon): class WorkRequestRelationDraft(BasicCommon): selection_doc = JSONField() - dataformat = ForeignKey('DataformatChoice', null=False, on_delete=CASCADE) + dataformat = ForeignKey('DataformatChoice', null=False, on_delete=PROTECT) producer = ForeignKey(WorkRequestDraft, related_name='produced_by', on_delete=CASCADE) consumer = ForeignKey(WorkRequestDraft, related_name='consumed_by', on_delete=CASCADE) input_role = ForeignKey(WorkIORole, related_name='inputs_work_request_relation_draft', on_delete=CASCADE) @@ -245,7 +246,7 @@ class WorkRequestRelationDraft(BasicCommon): class WorkRequestRelationBlueprint(BasicCommon): selection_doc = JSONField() - dataformat = ForeignKey('DataformatChoice', null=False, on_delete=CASCADE) + dataformat = ForeignKey('DataformatChoice', null=False, on_delete=PROTECT) producer = ForeignKey(WorkRequestBlueprint, related_name='produced_by', on_delete=CASCADE) consumer = ForeignKey(WorkRequestBlueprint, related_name='consumed_by', on_delete=CASCADE) input_role = ForeignKey(WorkIORole, related_name='inputs_work_request_relation_blueprint', on_delete=CASCADE) diff --git a/SAS/LSMR/test/t_lsmrapp_scheduling_functional.py b/SAS/LSMR/test/t_lsmrapp_scheduling_functional.py index abb275dee58f38dd1d1dc3056d8663b32156ae69..067181c3833a7da412664f13d77f8f2a8ea1f02f 100755 --- a/SAS/LSMR/test/t_lsmrapp_scheduling_functional.py +++ b/SAS/LSMR/test/t_lsmrapp_scheduling_functional.py @@ -350,26 +350,27 @@ class TaskTestCase(unittest.TestCase): # DELETE and check it's gone DELETE_and_assert_gone(self, url) - def test_task_CASCADE_behavior_on_type_deleted(self): + def test_task_PROTECT_behavior_on_type_choice_deleted(self): # create dependency that is safe to delete (enums are not populated / re-established between tests) type_data = {'value': 'kickme'} POST_and_assert_expected_response(self, BASE_URL + '/task_type_choice/', type_data, 201, type_data) - role_url = BASE_URL + '/task_type_choice/kickme/' + type_url = BASE_URL + '/task_type_choice/kickme/' # POST new item and verify test_data = dict(self.test_data_1) - test_data['type'] = role_url + test_data['type'] = type_url url = POST_and_assert_expected_response(self, BASE_URL + '/task/', test_data, 201, test_data)['url'] GET_and_assert_expected_response(self, url, 200, test_data) - # DELETE dependency and check it's gone - DELETE_and_assert_gone(self, role_url) - - # assert item gone - GET_and_assert_expected_response(self, url, 404, {}) + # Try to DELETE dependency, verify that was not successful + # Unfortunately we don't get a nice error in json, but a Django debug page on error 500... + response = requests.delete(type_url) + self.assertEqual(500, response.status_code) + self.assertTrue("ProtectedError" in str(response.content)) + GET_and_assert_expected_response(self, type_url, 200, type_data) - def test_task_PROTECT_behavior_on_state_deleted(self): + def test_task_PROTECT_behavior_on_state_choice_deleted(self): # create dependency that is safe to delete (enums are not populated / re-established between tests) state_data = {'value': 'kickme'} @@ -389,7 +390,7 @@ class TaskTestCase(unittest.TestCase): self.assertTrue("ProtectedError" in str(response.content)) GET_and_assert_expected_response(self, state_url, 200, state_data) - def test_task_PROTECT_behavior_on_requested_state_deleted(self): + def test_task_PROTECT_behavior_on_requested_state_choice_deleted(self): # create dependency that is safe to delete (enums are not populated / re-established between tests) state_data = {'value': 'kickmemore'} @@ -423,17 +424,18 @@ class TaskTestCase(unittest.TestCase): expected_data['work_request_blueprint'] = None GET_and_assert_expected_response(self, url, 200, expected_data) - def test_task_CASCADE_behavior_on_template_deleted(self): + def test_task_PROTECT_behavior_on_template_deleted(self): # POST new item and verify url = POST_and_assert_expected_response(self, BASE_URL + '/task/', self.test_data_2, 201, self.test_data_2)['url'] GET_and_assert_expected_response(self, url, 200, self.test_data_2) - # DELETE dependency and check it's gone - DELETE_and_assert_gone(self, self.task_template_url) - - # assert item gone - GET_and_assert_expected_response(self, url, 404, {}) + # Try to DELETE dependency, verify that was not successful + # Unfortunately we don't get a nice error in json, but a Django debug page on error 500... + response = requests.delete(self.task_template_url) + self.assertEqual(500, response.status_code) + self.assertTrue("ProtectedError" in str(response.content)) + GET_and_assert_expected_response(self, self.task_template_url, 200, TaskTemplateTestCase.test_data_1) class DataproductTestCase(unittest.TestCase): @@ -525,7 +527,7 @@ class DataproductTestCase(unittest.TestCase): # DELETE and check it's gone DELETE_and_assert_gone(self, url) - def test_dataproduct_CASCADE_behavior_on_dataformat_deleted(self): + def test_dataproduct_PROTECT_behavior_on_dataformat_choice_deleted(self): # create dependency that is safe to delete (enums are not populated / re-established between tests) dataformat_data = {'value': 'kickme'} @@ -538,11 +540,12 @@ class DataproductTestCase(unittest.TestCase): url = POST_and_assert_expected_response(self, BASE_URL + '/dataproduct/', test_data, 201, test_data)['url'] GET_and_assert_expected_response(self, url, 200, test_data) - # DELETE dependency and check it's gone - DELETE_and_assert_gone(self, dataformat_url) - - # assert item gone - GET_and_assert_expected_response(self, url, 404, {}) + # Try to DELETE dependency, verify that was not successful + # Unfortunately we don't get a nice error in json, but a Django debug page on error 500... + response = requests.delete(dataformat_url) + self.assertEqual(500, response.status_code) + self.assertTrue("ProtectedError" in str(response.content)) + GET_and_assert_expected_response(self, dataformat_url, 200, dataformat_data) def test_dataproduct_CASCADE_behavior_on_specification_template_deleted(self): @@ -632,7 +635,7 @@ class TaskIORoleTestCase(unittest.TestCase): # DELETE and check it's gone DELETE_and_assert_gone(self, url) - def test_task_io_role_CASCADE_behavior_on_role_deleted(self): + def test_task_io_role_PROTECT_behavior_on_role_choice_deleted(self): # create dependency that is safe to delete (enums are not populated / re-established between tests) role_data = {'value': 'kickme'} @@ -646,14 +649,15 @@ class TaskIORoleTestCase(unittest.TestCase): url = POST_and_assert_expected_response(self, BASE_URL + '/task_io_role/', test_data, 201, test_data)['url'] GET_and_assert_expected_response(self, url, 200, test_data) - # DELETE dependency and check it's gone - DELETE_and_assert_gone(self, role_url) - - # assert item gone - GET_and_assert_expected_response(self, url, 404, {}) + # Try to DELETE dependency, verify that was not successful + # Unfortunately we don't get a nice error in json, but a Django debug page on error 500... + response = requests.delete(role_url) + self.assertEqual(500, response.status_code) + self.assertTrue("ProtectedError" in str(response.content)) + GET_and_assert_expected_response(self, role_url, 200, role_data) - def test_task_io_role_CASCADE_behavior_on_datatype_deleted(self): + def test_task_io_role_PROTECT_behavior_on_datatype_choice_deleted(self): # create new dependency that is safe to delete (enums are not populated / re-established between tests) datatype_data = {'value': 'kickme'} @@ -666,11 +670,12 @@ class TaskIORoleTestCase(unittest.TestCase): url = POST_and_assert_expected_response(self, BASE_URL + '/task_io_role/', test_data, 201, test_data)['url'] GET_and_assert_expected_response(self, url, 200, test_data) - # DELETE dependency and check it's gone - DELETE_and_assert_gone(self, datatype_url) - - # assert item gone - GET_and_assert_expected_response(self, url, 404, {}) + # Try to DELETE dependency, verify that was not successful + # Unfortunately we don't get a nice error in json, but a Django debug page on error 500... + response = requests.delete(datatype_url) + self.assertEqual(500, response.status_code) + self.assertTrue("ProtectedError" in str(response.content)) + GET_and_assert_expected_response(self, datatype_url, 200, datatype_data) class DataproductRelationTestCase(unittest.TestCase): @@ -932,7 +937,7 @@ class AntennaSetTestCase(unittest.TestCase): # DELETE and check it's gone DELETE_and_assert_gone(self, url) - def test_antenna_set_CASCADE_behavior_on_station_type_choice_deleted(self): + def test_antenna_set_PROTECT_behavior_on_station_type_choice_deleted(self): # create dependency that is safe to delete (enums are not populated / re-established between tests) dataformat_data = {'value': 'kickme'} @@ -945,12 +950,12 @@ class AntennaSetTestCase(unittest.TestCase): url = POST_and_assert_expected_response(self, BASE_URL + '/antenna_set/', test_data, 201, test_data)['url'] GET_and_assert_expected_response(self, url, 200, test_data) - # DELETE dependency and check it's gone - DELETE_and_assert_gone(self, dataformat_url) - - # assert item gone - GET_and_assert_expected_response(self, url, 404, {}) - + # Try to DELETE dependency, verify that was not successful + # Unfortunately we don't get a nice error in json, but a Django debug page on error 500... + response = requests.delete(dataformat_url) + self.assertEqual(500, response.status_code) + self.assertTrue("ProtectedError" in str(response.content)) + GET_and_assert_expected_response(self, dataformat_url, 200, dataformat_data) if __name__ == "__main__": diff --git a/SAS/LSMR/test/t_lsmrapp_specification_functional.py b/SAS/LSMR/test/t_lsmrapp_specification_functional.py index fd1c32934768440b92d142fcaf22bc3082b2f5b8..af64e5aa1b14e12e4412e621dca604b108625b5f 100755 --- a/SAS/LSMR/test/t_lsmrapp_specification_functional.py +++ b/SAS/LSMR/test/t_lsmrapp_specification_functional.py @@ -836,7 +836,7 @@ class ProjectTestCase(unittest.TestCase): # DELETE and check it's gone DELETE_and_assert_gone(self, url) - def test_project_SET_NULL_behavior_on_cycle_deleted(self): + def test_project_PROTECT_behavior_on_cycle_deleted(self): # POST new item with dependencies cycle_url = POST_and_assert_expected_response(self, BASE_URL + '/cycle/', CycleTestCase.test_data_1, 201, CycleTestCase.test_data_1)['url'] @@ -847,12 +847,12 @@ class ProjectTestCase(unittest.TestCase): # verify GET_and_assert_expected_response(self, url, 200, test_data) - # DELETE dependency - DELETE_and_assert_gone(self, cycle_url) - - # assert - test_data['cycle'] = None - GET_and_assert_expected_response(self, url, 200, test_data) + # Try to DELETE dependency, verify that was not successful + # Unfortunately we don't get a nice error in json, but a Django debug page on error 500... + response = requests.delete(cycle_url) + self.assertEqual(500, response.status_code) + self.assertTrue("ProtectedError" in str(response.content)) + GET_and_assert_expected_response(self, cycle_url, 200, CycleTestCase.test_data_1) class RunSetTestCase(unittest.TestCase): @@ -941,7 +941,7 @@ class RunSetTestCase(unittest.TestCase): # DELETE and check it's gone DELETE_and_assert_gone(self, url) - def test_run_set_CASCADE_behavior_on_project_deleted(self): + def test_run_set_PROTECT_behavior_on_project_deleted(self): # POST new item url = POST_and_assert_expected_response(self, BASE_URL + '/run_set/', self.test_data_1, 201, self.test_data_1)['url'] @@ -949,11 +949,12 @@ class RunSetTestCase(unittest.TestCase): # verify GET_and_assert_expected_response(self, url, 200, self.test_data_1) - # DELETE dependency - DELETE_and_assert_gone(self, self.project_url) - - # assert - GET_and_assert_expected_response(self, url, 404, {}) + # Try to DELETE dependency, verify that was not successful + # Unfortunately we don't get a nice error in json, but a Django debug page on error 500... + response = requests.delete(self.project_url) + self.assertEqual(500, response.status_code) + self.assertTrue("ProtectedError" in str(response.content)) + GET_and_assert_expected_response(self, self.project_url, 200, ProjectTestCase.test_data_1) def test_run_set_SET_NULL_behavior_on_generator_template_deleted(self):