t_tmssapp_specification_functional.py 89.7 KB
Newer Older
1
#!/usr/bin/env python3
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

# Copyright (C) 2018    ASTRON (Netherlands Institute for Radio Astronomy)
# P.O. Box 2, 7990 AA Dwingeloo, The Netherlands
#
# This file is part of the LOFAR software suite.
# The LOFAR software suite is free software: you can redistribute it and/or
# modify it under the terms of the GNU General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# The LOFAR software suite is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.    See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with the LOFAR software suite. If not, see <http://www.gnu.org/licenses/>.

# $Id:  $

22 23 24

# This functional test talks to the API like a regular user would.
# It is supposed to cover all REST http methods for all ViewSets.
25 26 27
# todo: I am still a bit under the impression that we re-test Django functionality that we can expect to just work
# todo: with some of these tests. On the other hand a lot of these provide us a nice basis for differentiating out
# todo: behavior in a controlled way.
28 29
# todo: We should probably also fully test behavior wrt mandatory and nullable fields.

30
from datetime import datetime
31
import unittest
32 33 34 35
import logging
logger = logging.getLogger(__name__)
logging.basicConfig(format='%(asctime)s %(levelname)s %(message)s', level=logging.INFO)

36 37 38
# Do Mandatory setup step:
# use setup/teardown magic for tmss test database, ldap server and django server
# (ignore pycharm unused import statement, python unittests does use at RunTime the tmss_test_environment_unittest_setup module)
39 40
from lofar.sas.tmss.test.tmss_test_environment_unittest_setup import *

41 42 43
# import and setup test data creator
from lofar.sas.tmss.test.tmss_test_data_rest import TMSSRESTTestDataCreator
test_data_creator = TMSSRESTTestDataCreator(BASE_URL, AUTH)
44

45
class BasicFunctionTestCase(unittest.TestCase):
46
    # todo: test_welcome_page (once we have one :))
47
    pass
48 49


50
class GeneratorTemplateTestCase(unittest.TestCase):
51
    def test_generator_template_list_apiformat(self):
52
        r = requests.get(BASE_URL + '/generator_template/?format=api', auth=AUTH)
53
        self.assertEqual(r.status_code, 200)
54
        self.assertTrue("Generator Template List" in r.content.decode('utf8'))
55

56
    def test_generator_template_GET_nonexistant_raises_error(self):
57
        GET_and_assert_expected_response(self, BASE_URL + '/generator_template/1234321/', 404, {})
58 59 60 61

    def test_generator_template_POST_and_GET(self):

        # POST and GET a new item and assert correctness
62
        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/generator_template/', test_data_creator.GeneratorTemplate(), 201, test_data_creator.GeneratorTemplate())
63
        url = r_dict['url']
64
        GET_and_assert_expected_response(self, url, 200, test_data_creator.GeneratorTemplate())
65 66

    def test_generator_template_PUT_invalid_raises_error(self):
67
        PUT_and_assert_expected_response(self, BASE_URL + '/generator_template/9876789876/', test_data_creator.GeneratorTemplate(), 404, {})
68 69 70 71

    def test_generator_template_PUT(self):

        # POST new item, verify
72
        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/generator_template/', test_data_creator.GeneratorTemplate(), 201, test_data_creator.GeneratorTemplate())
73
        url = r_dict['url']
74
        GET_and_assert_expected_response(self, url, 200, test_data_creator.GeneratorTemplate())
75 76

        # PUT new values, verify
77 78
        PUT_and_assert_expected_response(self, url, test_data_creator.GeneratorTemplate("generatortemplate2"), 200, test_data_creator.GeneratorTemplate("generatortemplate2"))
        GET_and_assert_expected_response(self, url, 200, test_data_creator.GeneratorTemplate("generatortemplate2"))
79 80 81 82

    def test_generator_template_PATCH(self):

        # POST new item, verify
83
        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/generator_template/', test_data_creator.GeneratorTemplate(), 201, test_data_creator.GeneratorTemplate())
84
        url = r_dict['url']
85
        GET_and_assert_expected_response(self, url, 200, test_data_creator.GeneratorTemplate())
86

87 88 89
        test_patch = {"version": 'v6.28318530718',
                      "schema": {"mykey": "my better value"}}

90
        # PATCH item and verify
91
        PATCH_and_assert_expected_response(self, url, test_patch, 200, test_patch)
92
        expected_data = dict(test_data_creator.GeneratorTemplate())
93
        expected_data.update(test_patch)
94
        GET_and_assert_expected_response(self, url, 200, expected_data)
95 96 97 98

    def test_generator_template_DELETE(self):

        # POST new item, verify
99
        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/generator_template/', test_data_creator.GeneratorTemplate(), 201, test_data_creator.GeneratorTemplate())
100
        url = r_dict['url']
101
        GET_and_assert_expected_response(self, url, 200, test_data_creator.GeneratorTemplate())
102 103 104 105

        # DELETE and check it's gone
        DELETE_and_assert_gone(self, url)

106

107
class SchedulingUnitTemplateTestCase(unittest.TestCase):
108
    def test_scheduling_unit_template_list_apiformat(self):
109
        r = requests.get(BASE_URL + '/scheduling_unit_template/?format=api', auth=AUTH)
110
        self.assertEqual(r.status_code, 200)
111
        self.assertTrue("Scheduling Unit Template List" in r.content.decode('utf8'))
112

113 114
    def test_scheduling_unit_template_GET_nonexistant_raises_error(self):
        GET_and_assert_expected_response(self, BASE_URL + '/scheduling_unit_template/1234321/', 404, {})
115

116
    def test_scheduling_unit_template_POST_and_GET(self):
117 118

        # POST and GET a new item and assert correctness
119
        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/scheduling_unit_template/', test_data_creator.SchedulingUnitTemplate(), 201, test_data_creator.SchedulingUnitTemplate())
120
        url = r_dict['url']
121
        GET_and_assert_expected_response(self, url+'?format=json', 200, test_data_creator.SchedulingUnitTemplate())
122

123
    def test_scheduling_unit_template_PUT_invalid_raises_error(self):
124
        PUT_and_assert_expected_response(self, BASE_URL + '/scheduling_unit_template/9876789876/', test_data_creator.SchedulingUnitTemplate(), 404, {})
125

126
    def test_scheduling_unit_template_PUT(self):
127 128

        # POST new item, verify
129
        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/scheduling_unit_template/', test_data_creator.SchedulingUnitTemplate(), 201, test_data_creator.SchedulingUnitTemplate())
130
        url = r_dict['url']
131
        GET_and_assert_expected_response(self, url, 200, test_data_creator.SchedulingUnitTemplate())
132 133

        # PUT new values, verify
134 135
        PUT_and_assert_expected_response(self, url, test_data_creator.SchedulingUnitTemplate("schedulingunittemplate2"), 200, test_data_creator.SchedulingUnitTemplate("schedulingunittemplate2"))
        GET_and_assert_expected_response(self, url, 200, test_data_creator.SchedulingUnitTemplate("schedulingunittemplate2"))
136

137
    def test_scheduling_unit_template_PATCH(self):
138 139

        # POST new item, verify
140
        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/scheduling_unit_template/', test_data_creator.SchedulingUnitTemplate(), 201, test_data_creator.SchedulingUnitTemplate())
141
        url = r_dict['url']
142
        GET_and_assert_expected_response(self, url, 200, test_data_creator.SchedulingUnitTemplate())
143

144 145 146
        test_patch = {"version": 'v6.28318530718',
                      "schema": {"mykey": "my better value"}}

147
        # PATCH item and verify
148
        PATCH_and_assert_expected_response(self, url, test_patch, 200, test_patch)
149
        expected_data = dict(test_data_creator.SchedulingUnitTemplate())
150
        expected_data.update(test_patch)
151 152
        GET_and_assert_expected_response(self, url, 200, expected_data)

153
    def test_scheduling_unit_template_DELETE(self):
154 155

        # POST new item, verify
156
        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/scheduling_unit_template/', test_data_creator.SchedulingUnitTemplate(), 201, test_data_creator.SchedulingUnitTemplate())
157
        url = r_dict['url']
158
        GET_and_assert_expected_response(self, url, 200, test_data_creator.SchedulingUnitTemplate())
159 160 161

        # DELETE and check it's gone
        DELETE_and_assert_gone(self, url)
162

163
class TaskTemplateTestCase(unittest.TestCase):
164

165
    def test_task_template_list_apiformat(self):
166
        r = requests.get(BASE_URL + '/task_template/?format=api', auth=AUTH)
167
        self.assertEqual(r.status_code, 200)
168
        self.assertTrue("Task Template List" in r.content.decode('utf8'))
169

170 171
    def test_task_template_GET_nonexistant_raises_error(self):
        GET_and_assert_expected_response(self, BASE_URL + '/task_template/1234321/', 404, {})
172

173
    def test_task_template_POST_and_GET(self):
174
        # POST and GET a new item and assert correctness
175 176
        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/task_template/', test_data_creator.TaskTemplate(), 201,
                                                   test_data_creator.TaskTemplate())
177
        url = r_dict['url']
178
        GET_and_assert_expected_response(self, url + '?format=json', 200, test_data_creator.TaskTemplate())
179

180
    def test_task_template_PUT_invalid_raises_error(self):
181
        PUT_and_assert_expected_response(self, BASE_URL + '/task_template/9876789876/', test_data_creator.TaskTemplate(), 404, {})
182

183
    def test_task_template_PUT(self):
184
        # POST new item, verify
185 186
        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/task_template/', test_data_creator.TaskTemplate(), 201,
                                                   test_data_creator.TaskTemplate())
187
        url = r_dict['url']
188
        GET_and_assert_expected_response(self, url, 200, test_data_creator.TaskTemplate())
189 190

        # PUT new values, verify
191 192
        PUT_and_assert_expected_response(self, url, test_data_creator.TaskTemplate("tasktemplate2"), 200, test_data_creator.TaskTemplate("tasktemplate2"))
        GET_and_assert_expected_response(self, url, 200, test_data_creator.TaskTemplate("tasktemplate2"))
193

194
    def test_task_template_PATCH(self):
195
        # POST new item, verify
196 197
        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/task_template/', test_data_creator.TaskTemplate(), 201,
                                                   test_data_creator.TaskTemplate())
198
        url = r_dict['url']
199
        GET_and_assert_expected_response(self, url, 200, test_data_creator.TaskTemplate())
200

201 202 203
        test_patch = {"version": 'v6.28318530718',
                      "schema": {"mykey": "my better value"},
                      }
204
        # PATCH item and verify
205
        PATCH_and_assert_expected_response(self, url, test_patch, 200, test_patch)
206
        expected_data = dict(test_data_creator.TaskTemplate())
207
        expected_data.update(test_patch)
208 209
        GET_and_assert_expected_response(self, url, 200, expected_data)

210
    def test_task_template_DELETE(self):
211
        # POST new item, verify
212 213
        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/task_template/', test_data_creator.TaskTemplate(), 201,
                                                   test_data_creator.TaskTemplate())
214
        url = r_dict['url']
215
        GET_and_assert_expected_response(self, url, 200, test_data_creator.TaskTemplate())
216 217 218 219

        # DELETE and check it's gone
        DELETE_and_assert_gone(self, url)

220

221
class WorkRelationSelectionTemplateTestCase(unittest.TestCase):
222
    def test_work_relation_selection_template_list_apiformat(self):
223
        r = requests.get(BASE_URL + '/work_relation_selection_template/?format=api', auth=AUTH)
224 225 226 227 228 229 230 231 232
        self.assertEqual(r.status_code, 200)
        self.assertTrue("Work Relation Selection Template List" in r.content.decode('utf8'))

    def test_work_relation_selection_template_GET_nonexistant_raises_error(self):
        GET_and_assert_expected_response(self, BASE_URL + '/work_relation_selection_template/1234321/', 404, {})

    def test_work_relation_selection_template_POST_and_GET(self):

        # POST and GET a new item and assert correctness
233
        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/work_relation_selection_template/', test_data_creator.WorkRelationSelectionTemplate(), 201, test_data_creator.WorkRelationSelectionTemplate())
234
        url = r_dict['url']
235
        GET_and_assert_expected_response(self, url+'?format=json', 200, test_data_creator.WorkRelationSelectionTemplate())
236 237

    def test_work_relation_selection_template_PUT_invalid_raises_error(self):
238
        PUT_and_assert_expected_response(self, BASE_URL + '/work_relation_selection_template/9876789876/', test_data_creator.WorkRelationSelectionTemplate(), 404, {})
239 240 241 242

    def test_work_relation_selection_template_PUT(self):

        # POST new item, verify
243
        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/work_relation_selection_template/', test_data_creator.WorkRelationSelectionTemplate(), 201, test_data_creator.WorkRelationSelectionTemplate())
244
        url = r_dict['url']
245
        GET_and_assert_expected_response(self, url, 200, test_data_creator.WorkRelationSelectionTemplate())
246 247

        # PUT new values, verify
248 249
        PUT_and_assert_expected_response(self, url, test_data_creator.WorkRelationSelectionTemplate("workrelationselectiontemplate2"), 200, test_data_creator.WorkRelationSelectionTemplate("workrelationselectiontemplate2"))
        GET_and_assert_expected_response(self, url, 200, test_data_creator.WorkRelationSelectionTemplate("workrelationselectiontemplate2"))
250 251 252 253

    def test_work_relation_selection_template_PATCH(self):

        # POST new item, verify
254
        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/work_relation_selection_template/', test_data_creator.WorkRelationSelectionTemplate(), 201, test_data_creator.WorkRelationSelectionTemplate())
255
        url = r_dict['url']
256
        GET_and_assert_expected_response(self, url, 200, test_data_creator.WorkRelationSelectionTemplate())
257

258 259 260 261
        test_patch = {"version": 'v6.28318530718',
                      "schema": {"mykey": "my better value"},
                      }

262
        # PATCH item and verify
263
        PATCH_and_assert_expected_response(self, url, test_patch, 200, test_patch)
264
        expected_data = dict(test_data_creator.WorkRelationSelectionTemplate())
265
        expected_data.update(test_patch)
266 267 268 269 270
        GET_and_assert_expected_response(self, url, 200, expected_data)

    def test_work_relation_selection_template_DELETE(self):

        # POST new item, verify
271
        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/work_relation_selection_template/', test_data_creator.WorkRelationSelectionTemplate(), 201, test_data_creator.WorkRelationSelectionTemplate())
272
        url = r_dict['url']
273
        GET_and_assert_expected_response(self, url, 200, test_data_creator.WorkRelationSelectionTemplate())
274 275 276

        # DELETE and check it's gone
        DELETE_and_assert_gone(self, url)
277

278

279
class TaskConnectorsTestCase(unittest.TestCase):
280 281 282 283
    @classmethod
    def setUpClass(cls) -> None:
        cls.input_of_url = test_data_creator.post_data_and_get_url(test_data_creator.TaskTemplate(), '/task_template/')
        cls.output_of_url = test_data_creator.post_data_and_get_url(test_data_creator.TaskTemplate(), '/task_template/')
284

285
    def test_task_connectors_list_apiformat(self):
286
        r = requests.get(BASE_URL + '/task_connectors/?format=api', auth=AUTH)
287
        self.assertEqual(r.status_code, 200)
288
        self.assertTrue("Task Connectors List" in r.content.decode('utf8'))
289

290 291
    def test_task_connectors_GET_nonexistant_raises_error(self):
        GET_and_assert_expected_response(self, BASE_URL + '/task_connectors/1234321/', 404, {})
292

293
    def test_task_connectors_POST_and_GET(self):
294
        tc_test_data = test_data_creator.TaskConnectors(input_of_url=self.input_of_url, output_of_url=self.output_of_url)
295
        # POST and GET a new item and assert correctness
296
        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/task_connectors/', tc_test_data, 201, tc_test_data)
297
        url = r_dict['url']
298
        GET_and_assert_expected_response(self, url, 200, tc_test_data)
299

300
    def test_task_connectors_POST_invalid_role_raises_error(self):
301 302

        # POST a new item with invalid choice
303
        test_data_invalid_role = dict(test_data_creator.TaskConnectors(input_of_url=self.input_of_url, output_of_url=self.output_of_url))
304
        test_data_invalid_role['role'] = BASE_URL + '/role/forbidden/'
305
        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/task_connectors/', test_data_invalid_role, 400, {})
306
        self.assertTrue('Invalid hyperlink' in str(r_dict['role']))
307

308
    def test_task_connectors_POST_invalid_datatype_raises_error(self):
309 310

        # POST a new item with invalid choice
311
        test_data_invalid = dict(test_data_creator.TaskConnectors(input_of_url=self.input_of_url, output_of_url=self.output_of_url))
312
        test_data_invalid['datatype'] = BASE_URL + '/datatype/forbidden/'
313
        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/task_connectors/', test_data_invalid, 400, {})
314
        self.assertTrue('Invalid hyperlink' in str(r_dict['datatype']))
315

316
    def test_task_connectors_POST_invalid_dataformats_raises_error(self):
317 318

        # POST a new item with invalid choice
319
        test_data_invalid = dict(test_data_creator.TaskConnectors(input_of_url=self.input_of_url, output_of_url=self.output_of_url))
320
        test_data_invalid['dataformats'] = [BASE_URL + '/dataformat/forbidden/']
321
        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/task_connectors/', test_data_invalid, 400, {})
322
        self.assertTrue('Invalid hyperlink' in str(r_dict['dataformats']))
323

324
    def test_task_connectors_POST_nonexistant_input_of_raises_error(self):
325 326

        # POST a new item with wrong reference
327
        test_data_invalid = dict(test_data_creator.TaskConnectors(input_of_url=self.input_of_url, output_of_url=self.output_of_url))
328 329 330
        test_data_invalid['input_of'] = BASE_URL + "/task_template/6353748/"
        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/task_connectors/', test_data_invalid, 400, {})
        self.assertTrue('Invalid hyperlink' in str(r_dict['input_of']))
331

332
    def test_task_connectors_POST_nonexistant_output_of_raises_error(self):
333 334

        # POST a new item with wrong reference
335
        test_data_invalid = dict(test_data_creator.TaskConnectors(input_of_url=self.input_of_url, output_of_url=self.output_of_url))
336 337 338
        test_data_invalid['output_of'] = BASE_URL + "/task_template/6353748/"
        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/task_connectors/', test_data_invalid, 400, {})
        self.assertTrue('Invalid hyperlink' in str(r_dict['output_of']))
339

340
    def test_task_connectors_POST_existing_outputs_works(self):
341 342

        # First POST a new item to reference
343
        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/task_template/', test_data_creator.TaskTemplate(), 201, test_data_creator.TaskTemplate())
344
        url = r_dict['url']
345 346

        # POST a new item with correct reference
347
        test_data_valid = dict(test_data_creator.TaskConnectors(input_of_url=self.input_of_url, output_of_url=self.output_of_url))
348 349
        test_data_valid['output_of'] = url
        POST_and_assert_expected_response(self, BASE_URL + '/task_connectors/', test_data_valid, 201, test_data_valid)
350

351
    def test_task_connectors_PUT_nonexistant_raises_error(self):
352
        PUT_and_assert_expected_response(self, BASE_URL + '/task_connectors/9876789876/', test_data_creator.TaskConnectors(input_of_url=self.input_of_url, output_of_url=self.output_of_url), 404, {})
353

354
    def test_task_connectors_PUT(self):
355 356
        tc_test_data1 = test_data_creator.TaskConnectors(role="correlator", input_of_url=self.input_of_url, output_of_url=self.output_of_url)
        tc_test_data2 = test_data_creator.TaskConnectors(role="beamformer", input_of_url=self.input_of_url, output_of_url=self.output_of_url)
357

358
        # POST new item, verify
359
        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/task_connectors/', tc_test_data1, 201, tc_test_data1)
360
        url = r_dict['url']
361
        GET_and_assert_expected_response(self, url, 200, tc_test_data1)
362 363

        # PUT new values, verify
364 365
        PUT_and_assert_expected_response(self, url, tc_test_data2, 200, tc_test_data2)
        GET_and_assert_expected_response(self, url, 200, tc_test_data2)
366

367
    def test_task_connectors_PATCH(self):
368
        tc_test_data = test_data_creator.TaskConnectors(input_of_url=self.input_of_url, output_of_url=self.output_of_url)
369

370
        # POST new item, verify
371
        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/task_connectors/', tc_test_data, 201, tc_test_data)
372
        url = r_dict['url']
373
        GET_and_assert_expected_response(self, url, 200, tc_test_data)
374

375 376 377 378
        test_patch = {"role": BASE_URL + '/role/calibrator/',
                      "dataformats": [BASE_URL + '/dataformat/Beamformed/',
                                      BASE_URL + '/dataformat/MeasurementSet/']}

379
        # PATCH item and verify
380
        PATCH_and_assert_expected_response(self, url, test_patch, 200, test_patch)
381
        expected_data = dict(tc_test_data)
382
        expected_data.update(test_patch)
383
        GET_and_assert_expected_response(self, url, 200, expected_data)
384

385
    def test_task_connectors_DELETE(self):
386
        tc_test_data = test_data_creator.TaskConnectors(input_of_url=self.input_of_url, output_of_url=self.output_of_url)
387

388
        # POST new item, verify
389
        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/task_connectors/', tc_test_data, 201, tc_test_data)
390
        url = r_dict['url']
391
        GET_and_assert_expected_response(self, url, 200, tc_test_data)
392 393 394 395 396

        # DELETE and check it's gone
        DELETE_and_assert_gone(self, url)


397
    def test_task_relation_blueprint_CASCADE_behavior_on_inputs_template_deleted(self):
398 399
        input_of_url = test_data_creator.post_data_and_get_url(test_data_creator.TaskTemplate(), '/task_template/')
        tc_test_data = test_data_creator.TaskConnectors(input_of_url=input_of_url, output_of_url=self.output_of_url)
400 401

        # POST new item
402
        url = POST_and_assert_expected_response(self, BASE_URL + '/task_connectors/', tc_test_data, 201, tc_test_data)['url']
403 404

        # verify
405
        GET_and_assert_expected_response(self, url, 200, tc_test_data)
406 407

        # DELETE dependency
408
        DELETE_and_assert_gone(self, input_of_url)
409 410 411 412 413

        # assert
        GET_and_assert_expected_response(self, url, 404, {})


414
    def test_task_relation_blueprint_CASCADE_behavior_on_outputs_template_deleted(self):
415 416
        output_of_url = test_data_creator.post_data_and_get_url(test_data_creator.TaskTemplate(), '/task_template/')
        tc_test_data = test_data_creator.TaskConnectors(input_of_url=self.input_of_url, output_of_url=output_of_url)
417 418

        # POST new item
419
        url = POST_and_assert_expected_response(self, BASE_URL + '/task_connectors/', tc_test_data, 201, tc_test_data)['url']
420 421

        # verify
422
        GET_and_assert_expected_response(self, url, 200, tc_test_data)
423 424

        # DELETE dependency
425
        DELETE_and_assert_gone(self, output_of_url)
426 427 428 429 430

        # assert
        GET_and_assert_expected_response(self, url, 404, {})


431
class DefaultTemplates(unittest.TestCase):
432 433
    def test_default_generator_template_POST(self):
        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/generator_template/',
434 435
                                                   test_data_creator.GeneratorTemplate(), 201,
                                                   test_data_creator.GeneratorTemplate())
436 437
        url = r_dict['url']

438
        test_data_1 = dict(test_data_creator.DefaultTemplates())
439 440 441
        test_data_1['template'] = url
        POST_and_assert_expected_response(self, BASE_URL + '/default_generator_template/', test_data_1, 201, test_data_1)

442 443
    def test_default_scheduling_unit_template_POST(self):
        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/scheduling_unit_template/',
444 445
                                                   test_data_creator.SchedulingUnitTemplate(), 201,
                                                   test_data_creator.SchedulingUnitTemplate())
446 447
        url = r_dict['url']

448
        test_data_1 = dict(test_data_creator.DefaultTemplates())
449
        test_data_1['template'] = url
450
        POST_and_assert_expected_response(self, BASE_URL + '/default_scheduling_unit_template/', test_data_1, 201, test_data_1)
451

452 453
    def test_default_task_template_POST(self):
        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/task_template/',
454 455
                                                   test_data_creator.TaskTemplate(), 201,
                                                   test_data_creator.TaskTemplate())
456 457
        url = r_dict['url']

458
        test_data_1 = dict(test_data_creator.DefaultTemplates())
459
        test_data_1['template'] = url
460
        POST_and_assert_expected_response(self, BASE_URL + '/default_task_template/', test_data_1, 201, test_data_1)
461 462 463 464


    def test_default_work_relation_selection_template_POST(self):
        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/work_relation_selection_template/',
465 466
                                                   test_data_creator.WorkRelationSelectionTemplate(), 201,
                                                   test_data_creator.WorkRelationSelectionTemplate())
467 468
        url = r_dict['url']

469
        test_data_1 = dict(test_data_creator.DefaultTemplates())
470 471 472
        test_data_1['template'] = url
        POST_and_assert_expected_response(self, BASE_URL + '/default_work_relation_selection_template/', test_data_1, 201, test_data_1)

473 474 475 476
    def test_default_generator_template_PROTECT_behavior_on_template_deleted(self):

        # POST with dependency
        template_url = POST_and_assert_expected_response(self, BASE_URL + '/generator_template/',
477 478 479
                                                test_data_creator.GeneratorTemplate(), 201,
                                                test_data_creator.GeneratorTemplate())['url']
        test_data = dict(test_data_creator.DefaultTemplates("defaulttemplate2"))
480 481 482 483 484 485
        test_data['template'] = template_url
        POST_and_assert_expected_response(self, BASE_URL + '/default_generator_template/',
                                          test_data, 201, 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...
486
        response = requests.delete(template_url, auth=AUTH)
487 488
        self.assertEqual(500, response.status_code)
        self.assertTrue("ProtectedError" in str(response.content))
489
        GET_and_assert_expected_response(self, template_url, 200, test_data_creator.GeneratorTemplate())
490

491
    def test_default_scheduling_unit_template_PROTECT_behavior_on_template_deleted(self):
492 493

        # POST with dependency
494
        template_url = POST_and_assert_expected_response(self, BASE_URL + '/scheduling_unit_template/',
495 496 497
                                                test_data_creator.SchedulingUnitTemplate(), 201,
                                                test_data_creator.SchedulingUnitTemplate())['url']
        test_data = dict(test_data_creator.DefaultTemplates("defaulttemplate2"))
498
        test_data['template'] = template_url
499
        POST_and_assert_expected_response(self, BASE_URL + '/default_scheduling_unit_template/',
500 501 502 503
                                          test_data, 201, 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...
504
        response = requests.delete(template_url, auth=AUTH)
505 506
        self.assertEqual(500, response.status_code)
        self.assertTrue("ProtectedError" in str(response.content))
507
        GET_and_assert_expected_response(self, template_url, 200, test_data_creator.SchedulingUnitTemplate())
508 509


510
    def test_default_task_template_PROTECT_behavior_on_template_deleted(self):
511 512

        # POST with dependency
513
        template_url = POST_and_assert_expected_response(self, BASE_URL + '/task_template/',
514 515 516
                                                test_data_creator.TaskTemplate(), 201,
                                                test_data_creator.TaskTemplate())['url']
        test_data = dict(test_data_creator.DefaultTemplates("defaulttemplate2"))
517
        test_data['template'] = template_url
518
        POST_and_assert_expected_response(self, BASE_URL + '/default_task_template/',
519 520 521 522
                                          test_data, 201, 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...
523
        response = requests.delete(template_url, auth=AUTH)
524 525
        self.assertEqual(500, response.status_code)
        self.assertTrue("ProtectedError" in str(response.content))
526
        GET_and_assert_expected_response(self, template_url, 200, test_data_creator.TaskTemplate())
527 528 529 530 531

    def test_default_work_relation_selection_template_PROTECT_behavior_on_template_deleted(self):

        # POST with dependency
        template_url = POST_and_assert_expected_response(self, BASE_URL + '/work_relation_selection_template/',
532 533 534
                                                test_data_creator.WorkRelationSelectionTemplate(), 201,
                                                test_data_creator.WorkRelationSelectionTemplate())['url']
        test_data = dict(test_data_creator.DefaultTemplates("defaulttemplate2"))
535 536 537 538 539 540
        test_data['template'] = template_url
        POST_and_assert_expected_response(self, BASE_URL + '/default_work_relation_selection_template/',
                                          test_data, 201, 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...
541
        response = requests.delete(template_url, auth=AUTH)
542 543
        self.assertEqual(500, response.status_code)
        self.assertTrue("ProtectedError" in str(response.content))
544
        GET_and_assert_expected_response(self, template_url, 200, test_data_creator.WorkRelationSelectionTemplate())
545

546

547
class CycleTestCase(unittest.TestCase):
548
    def test_cycle_list_apiformat(self):
549
        r = requests.get(BASE_URL + '/cycle/?format=api', auth=AUTH)
550 551 552 553 554 555 556 557 558
        self.assertEqual(r.status_code, 200)
        self.assertTrue("Cycle List" in r.content.decode('utf8'))

    def test_cycle_GET_nonexistant_raises_error(self):
        GET_and_assert_expected_response(self, BASE_URL + '/cycle/1234321/', 404, {})

    def test_cycle_POST_and_GET(self):

        # POST and GET a new item and assert correctness
559
        cycle_test_data = test_data_creator.Cycle()
560
        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/cycle/', cycle_test_data, 201, cycle_test_data)
561
        url = r_dict['url']
562
        GET_and_assert_expected_response(self, url, 200, cycle_test_data)
563 564

    def test_cycle_PUT_invalid_raises_error(self):
565
        PUT_and_assert_expected_response(self, BASE_URL + '/cycle/9876789876/', test_data_creator.Cycle(), 404, {})
566 567

    def test_cycle_PUT(self):
568
        cycle_test_data = test_data_creator.Cycle()
569 570

        # POST new item, verify
571
        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/cycle/', cycle_test_data, 201, cycle_test_data)
572
        url = r_dict['url']
573
        GET_and_assert_expected_response(self, url, 200, cycle_test_data)
574 575

        # PUT new values, verify
576
        test_data = dict(test_data_creator.Cycle("other description"))
577
        test_data['name'] = cycle_test_data['name']  # since name is PK, need to keep that unchanged
578 579
        PUT_and_assert_expected_response(self, url, test_data, 200, test_data)
        GET_and_assert_expected_response(self, url, 200, test_data)
580 581

    def test_cycle_PATCH(self):
582
        cycle_test_data = test_data_creator.Cycle()
583 584

        # POST new item, verify
585

586
        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/cycle/', cycle_test_data, 201, cycle_test_data)
587
        url = r_dict['url']
588
        GET_and_assert_expected_response(self, url, 200, cycle_test_data)
589

590 591
        test_patch = {"start": datetime(year=2015, month=10, day=21).isoformat()}

592
        # PATCH item and verify
593
        PATCH_and_assert_expected_response(self, url, test_patch, 200, test_patch)
594
        expected_data = dict(cycle_test_data)
595
        expected_data.update(test_patch)
596 597 598
        GET_and_assert_expected_response(self, url, 200, expected_data)

    def test_cycle_DELETE(self):
599
        cycle_test_data = test_data_creator.Cycle()
600 601

        # POST new item, verify
602
        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/cycle/', cycle_test_data, 201, cycle_test_data)
603
        url = r_dict['url']
604
        GET_and_assert_expected_response(self, url, 200, cycle_test_data)
605 606 607 608 609

        # DELETE and check it's gone
        DELETE_and_assert_gone(self, url)


610
class ProjectTestCase(unittest.TestCase):
611
    def test_project_list_apiformat(self):
612
        r = requests.get(BASE_URL + '/project/?format=api', auth=AUTH)
613 614 615 616 617 618 619
        self.assertEqual(r.status_code, 200)
        self.assertTrue("Project List" in r.content.decode('utf8'))

    def test_project_GET_nonexistant_raises_error(self):
        GET_and_assert_expected_response(self, BASE_URL + '/project/1234321/', 404, {})

    def test_project_POST_and_GET(self):
620
        project_test_data = test_data_creator.Project()
621 622

        # POST and GET a new item and assert correctness
623
        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/project/', project_test_data, 201, project_test_data)
624
        url = r_dict['url']
625
        GET_and_assert_expected_response(self, url, 200, project_test_data)
626 627

    def test_project_PUT_invalid_raises_error(self):
628
        PUT_and_assert_expected_response(self, BASE_URL + '/project/9876789876/', test_data_creator.Project(), 404, {})
629 630

    def test_project_PUT(self):
631
        project_test_data = test_data_creator.Project()
632 633

        # POST new item, verify
634
        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/project/', project_test_data, 201, project_test_data)
635
        url = r_dict['url']
636
        GET_and_assert_expected_response(self, url, 200, project_test_data)
637 638

        # PUT new values, verify
639
        test_data = dict(test_data_creator.Project("other description"))
640
        test_data['name'] = project_test_data['name']  # since name is PK, need to keep that unchanged
641 642
        PUT_and_assert_expected_response(self, url, test_data, 200, test_data)
        GET_and_assert_expected_response(self, url, 200, test_data)
643 644

    def test_project_PATCH(self):
645
        project_test_data = test_data_creator.Project()
646 647

        # POST new item, verify
648
        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/project/', project_test_data, 201, project_test_data)
649
        url = r_dict['url']
650
        GET_and_assert_expected_response(self, url, 200, project_test_data)
651

652 653 654
        test_patch = {"priority": 500,
                      "tags": ["SUPERIMPORTANT"]}

655
        # PATCH item and verify
656
        PATCH_and_assert_expected_response(self, url, test_patch, 200, test_patch)
657
        expected_data = dict(project_test_data)
658
        expected_data.update(test_patch)
659 660 661
        GET_and_assert_expected_response(self, url, 200, expected_data)

    def test_project_DELETE(self):
662
        project_test_data = test_data_creator.Project()
663 664

        # POST new item, verify
665
        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/project/', project_test_data, 201, project_test_data)
666
        url = r_dict['url']
667
        GET_and_assert_expected_response(self, url, 200, project_test_data)
668 669 670 671

        # DELETE and check it's gone
        DELETE_and_assert_gone(self, url)

672
    def test_project_PROTECT_behavior_on_cycle_deleted(self):
673 674

        # POST new item with dependencies
675
        cycle_test_data = test_data_creator.Cycle()
676
        cycle_url = POST_and_assert_expected_response(self, BASE_URL + '/cycle/', cycle_test_data, 201, cycle_test_data)['url']
677
        test_data = dict(test_data_creator.Project())
678 679 680 681 682 683
        test_data['cycle'] = cycle_url
        url = POST_and_assert_expected_response(self, BASE_URL + '/project/', test_data, 201, test_data)['url']

        # verify
        GET_and_assert_expected_response(self, url, 200, test_data)

684 685 686
        # add project reference to cycle test data (we make Django add that to the cycle in serializer)
        cycle_test_data['projects'] = [url]  # add the

687 688
        # 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...
689
        response = requests.delete(cycle_url, auth=AUTH)
690 691
        self.assertEqual(500, response.status_code)
        self.assertTrue("ProtectedError" in str(response.content))
692
        GET_and_assert_expected_response(self, cycle_url, 200, cycle_test_data)
693

694

695
class SchedulingSetTestCase(unittest.TestCase):
696
    def test_scheduling_set_list_apiformat(self):
697
        r = requests.get(BASE_URL + '/scheduling_set/?format=api', auth=AUTH)
698
        self.assertEqual(r.status_code, 200)
699
        self.assertTrue("Scheduling Set List" in r.content.decode('utf8'))
700

701 702
    def test_scheduling_set_GET_nonexistant_raises_error(self):
        GET_and_assert_expected_response(self, BASE_URL + '/scheduling_set/1234321/', 404, {})
703

704
    def test_scheduling_set_POST_and_GET(self):
705
        schedulingset_test_data = test_data_creator.SchedulingSet()
706 707

        # POST and GET a new item and assert correctness
708
        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/scheduling_set/', schedulingset_test_data, 201, schedulingset_test_data)
709
        url = r_dict['url']
710
        GET_and_assert_expected_response(self, url, 200, schedulingset_test_data)
711

712
    def test_scheduling_set_PUT_invalid_raises_error(self):
713
        schedulingset_test_data = test_data_creator.SchedulingSet()
714
        PUT_and_assert_expected_response(self, BASE_URL + '/scheduling_set/9876789876/', schedulingset_test_data, 404, {})
715

716
    def test_scheduling_set_PUT(self):
717 718
        project_url = test_data_creator.post_data_and_get_url(test_data_creator.Project(), '/project/')
        schedulingset_test_data = test_data_creator.SchedulingSet(project_url=project_url)
719 720

        # POST new item, verify
721
        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/scheduling_set/', schedulingset_test_data, 201, schedulingset_test_data)
722
        url = r_dict['url']
723
        GET_and_assert_expected_response(self, url, 200, schedulingset_test_data)
724

725
        schedulingset_test_data2 = test_data_creator.SchedulingSet("schedulingset2", project_url=project_url)
726
        # PUT new values, verify
727 728
        PUT_and_assert_expected_response(self, url, schedulingset_test_data2, 200, schedulingset_test_data2)
        GET_and_assert_expected_response(self, url, 200, schedulingset_test_data2)
729

730
    def test_scheduling_set_PATCH(self):
731
        schedulingset_test_data = test_data_creator.SchedulingSet()
732 733

        # POST new item, verify
734
        r_dict = POST_and_assert_expected_response(self, BASE_URL + '/scheduling_set/', schedulingset_test_data, 201, schedulingset_test_data)
735
        url = r_dict['url']
736
        GET_and_assert_expected_response(self, url, 200, schedulingset_test_data)
737

738 739 740
        test_patch = {"description": "This is a new and improved description",
                      "generator_doc": "{'para': 'meter'}"}

741
        # PATCH item and verify
742
        PATCH_and_assert_expected_response(self, url, test_patch, 200, test_patch)
743
        expected_data = dict(schedulingset_test_data)
744
        expected_data.update(test_patch)
745 746
        GET_and_assert_expected_response(self, url, 200, expected_data)

747
    def test_scheduling_set_DELETE(self):
748
        schedulingset_test_data = test_data_creator.SchedulingSet()