Example #1
0
class OperationServiceTest(BaseTestCase):
    """
    Test class for the introspection module. Some tests from here do async launches. For those
    cases Transactional tests won't work.
    """
    def setUp(self):
        """
        Reset the database before each test.
        """
        self.clean_database()
        initialize_storage()
        self.test_user = TestFactory.create_user()
        self.test_project = TestFactory.create_project(self.test_user)
        self.operation_service = OperationService()
        self.backup_hdd_size = TVBSettings.MAX_DISK_SPACE

    def tearDown(self):
        """
        Reset the database when test is done.
        """
        TVBSettings.MAX_DISK_SPACE = self.backup_hdd_size
        self.clean_database()

    def test_datatypes_groups(self):
        """
        Tests if the dataType group is set correct on the dataTypes resulted from the same operation group.
        """
        flow_service = FlowService()

        all_operations = dao.get_filtered_operations(self.test_project.id,
                                                     None)
        self.assertEqual(len(all_operations), 0,
                         "There should be no operation")

        algogroup = dao.find_group('tvb_test.adapters.testadapter3',
                                   'TestAdapter3')
        group, _ = flow_service.prepare_adapter(self.test_project.id,
                                                algogroup)
        adapter_instance = flow_service.build_adapter_instance(group)
        data = {'first_range': 'param_5', 'param_5': [1, 2]}
        ## Create Group of operations
        flow_service.fire_operation(adapter_instance, self.test_user,
                                    self.test_project.id, **data)

        all_operations = dao.get_filtered_operations(self.test_project.id,
                                                     None)
        self.assertEqual(len(all_operations), 1,
                         "Expected one operation group")
        self.assertEqual(all_operations[0][2], 2,
                         "Expected 2 operations in group")

        operation_group_id = all_operations[0][3]
        self.assertNotEquals(operation_group_id, None,
                             "The operation should be part of a group.")

        self.operation_service.stop_operation(all_operations[0][0])
        self.operation_service.stop_operation(all_operations[0][1])
        ## Make sure operations are executed
        self.operation_service.launch_operation(all_operations[0][0], False)
        self.operation_service.launch_operation(all_operations[0][1], False)

        resulted_datatypes = dao.get_datatype_in_group(operation_group_id)
        self.assertTrue(
            len(resulted_datatypes) >= 2,
            "Expected at least 2, but: " + str(len(resulted_datatypes)))

        dt = dao.get_datatype_by_id(resulted_datatypes[0].id)
        datatype_group = dao.get_datatypegroup_by_op_group_id(
            operation_group_id)
        self.assertEqual(dt.fk_datatype_group, datatype_group.id,
                         "DataTypeGroup is incorrect")

    def test_initiate_operation(self):
        """
        Test the actual operation flow by executing a test adapter.
        """
        module = "tvb_test.adapters.testadapter1"
        class_name = "TestAdapter1"
        group = dao.find_group(module, class_name)
        adapter = FlowService().build_adapter_instance(group)
        output = adapter.get_output()
        output_type = output[0].__name__
        data = {"test1_val1": 5, "test1_val2": 5}
        tmp_folder = FilesHelper().get_project_folder(self.test_project,
                                                      "TEMP")
        res = self.operation_service.initiate_operation(
            self.test_user,
            self.test_project.id,
            adapter,
            tmp_folder,
            method_name=ABCAdapter.LAUNCH_METHOD,
            **data)
        self.assertTrue(
            res.index("has finished.") > 10, "Operation didn't finish")
        group = dao.find_group(module, class_name)
        self.assertEqual(group.module, 'tvb_test.adapters.testadapter1',
                         "Wrong data stored.")
        self.assertEqual(group.classname, 'TestAdapter1', "Wrong data stored.")
        dts = dao.get_values_of_datatype(self.test_project.id, Datatype1)
        self.assertEqual(len(dts), 1)
        datatype = dao.get_datatype_by_id(dts[0][0])
        self.assertEqual(datatype.subject, DataTypeMetaData.DEFAULT_SUBJECT,
                         "Wrong data stored.")
        self.assertEqual(datatype.type, output_type, "Wrong data stored.")

    def test_delete_dt_free_HDD_space(self):
        """
        Launch two operations and give enough available space for user so that both should finish.
        """
        module = "tvb_test.adapters.testadapter3"
        class_name = "TestAdapterHDDRequired"
        group = dao.find_group(module, class_name)
        adapter = FlowService().build_adapter_instance(group)
        output = adapter.get_output()
        output_type = output[0].__name__
        data = {"test": 100}
        TVBSettings.MAX_DISK_SPACE = float(
            adapter.get_required_disk_size(**data))
        tmp_folder = FilesHelper().get_project_folder(self.test_project,
                                                      "TEMP")

        dts = dao.get_values_of_datatype(self.test_project.id, Datatype2)
        self.assertEqual(len(dts), 0)
        self.operation_service.initiate_operation(
            self.test_user,
            self.test_project.id,
            adapter,
            tmp_folder,
            method_name=ABCAdapter.LAUNCH_METHOD,
            **data)
        dts = dao.get_values_of_datatype(self.test_project.id, Datatype2)
        self.assertEqual(len(dts), 1)

        datatype = dao.get_datatype_by_id(dts[0][0])
        self.assertEqual(datatype.subject, DataTypeMetaData.DEFAULT_SUBJECT,
                         "Wrong data stored.")
        self.assertEqual(datatype.type, output_type, "Wrong data stored.")

        #Now update the maximum disk size to be the size of the previously resulted datatypes (transform from kB to MB)
        #plus what is estimated to be required from the next one (transform from B to MB)
        ProjectService().remove_datatype(self.test_project.id, datatype.gid)
        dts = dao.get_values_of_datatype(self.test_project.id, Datatype2)
        self.assertEqual(len(dts), 0)

        self.operation_service.initiate_operation(
            self.test_user,
            self.test_project.id,
            adapter,
            tmp_folder,
            method_name=ABCAdapter.LAUNCH_METHOD,
            **data)
        dts = dao.get_values_of_datatype(self.test_project.id, Datatype2)
        self.assertEqual(len(dts), 1)
        datatype = dao.get_datatype_by_id(dts[0][0])
        self.assertEqual(datatype.subject, DataTypeMetaData.DEFAULT_SUBJECT,
                         "Wrong data stored.")
        self.assertEqual(datatype.type, output_type, "Wrong data stored.")

    def test_launch_two_ops_HDD_with_space(self):
        """
        Launch two operations and give enough available space for user so that both should finish.
        """
        module = "tvb_test.adapters.testadapter3"
        class_name = "TestAdapterHDDRequired"
        group = dao.find_group(module, class_name)
        adapter = FlowService().build_adapter_instance(group)
        output = adapter.get_output()
        output_type = output[0].__name__
        data = {"test": 100}
        TVBSettings.MAX_DISK_SPACE = 2 * float(
            adapter.get_required_disk_size(**data))
        tmp_folder = FilesHelper().get_project_folder(self.test_project,
                                                      "TEMP")
        self.operation_service.initiate_operation(
            self.test_user,
            self.test_project.id,
            adapter,
            tmp_folder,
            method_name=ABCAdapter.LAUNCH_METHOD,
            **data)
        dts = dao.get_values_of_datatype(self.test_project.id, Datatype2)
        self.assertEqual(len(dts), 1)
        datatype = dao.get_datatype_by_id(dts[0][0])
        self.assertEqual(datatype.subject, DataTypeMetaData.DEFAULT_SUBJECT,
                         "Wrong data stored.")
        self.assertEqual(datatype.type, output_type, "Wrong data stored.")
        #Now update the maximum disk size to be the size of the previously resulted datatypes (transform from kB to MB)
        #plus what is estimated to be required from the next one (transform from B to MB)
        TVBSettings.MAX_DISK_SPACE = float(datatype.disk_size) + float(
            adapter.get_required_disk_size(**data))

        self.operation_service.initiate_operation(
            self.test_user,
            self.test_project.id,
            adapter,
            tmp_folder,
            method_name=ABCAdapter.LAUNCH_METHOD,
            **data)
        dts = dao.get_values_of_datatype(self.test_project.id, Datatype2)
        self.assertEqual(len(dts), 2)
        datatype = dao.get_datatype_by_id(dts[1][0])
        self.assertEqual(datatype.subject, DataTypeMetaData.DEFAULT_SUBJECT,
                         "Wrong data stored.")
        self.assertEqual(datatype.type, output_type, "Wrong data stored.")

    def test_launch_two_ops_HDD_full_space(self):
        """
        Launch two operations and give available space for user so that the first should finish,
        but after the update to the user hdd size the second should not.
        """
        module = "tvb_test.adapters.testadapter3"
        class_name = "TestAdapterHDDRequired"
        group = dao.find_group(module, class_name)
        adapter = FlowService().build_adapter_instance(group)
        output = adapter.get_output()
        output_type = output[0].__name__
        data = {"test": 100}
        TVBSettings.MAX_DISK_SPACE = (
            1 + float(adapter.get_required_disk_size(**data)))
        tmp_folder = FilesHelper().get_project_folder(self.test_project,
                                                      "TEMP")
        self.operation_service.initiate_operation(
            self.test_user,
            self.test_project.id,
            adapter,
            tmp_folder,
            method_name=ABCAdapter.LAUNCH_METHOD,
            **data)
        dts = dao.get_values_of_datatype(self.test_project.id, Datatype2)
        self.assertEqual(len(dts), 1)
        datatype = dao.get_datatype_by_id(dts[0][0])
        self.assertEqual(datatype.subject, DataTypeMetaData.DEFAULT_SUBJECT,
                         "Wrong data stored.")
        self.assertEqual(datatype.type, output_type, "Wrong data stored.")
        #Now update the maximum disk size to be less than size of the previously resulted datatypes (transform kB to MB)
        #plus what is estimated to be required from the next one (transform from B to MB)
        TVBSettings.MAX_DISK_SPACE = float(datatype.disk_size - 1) + float(
            adapter.get_required_disk_size(**data) - 1)

        self.assertRaises(NoMemoryAvailableException,
                          self.operation_service.initiate_operation,
                          self.test_user,
                          self.test_project.id,
                          adapter,
                          tmp_folder,
                          method_name=ABCAdapter.LAUNCH_METHOD,
                          **data)
        dts = dao.get_values_of_datatype(self.test_project.id, Datatype2)
        self.assertEqual(len(dts), 1)

    def test_launch_operation_HDD_with_space(self):
        """
        Test the actual operation flow by executing a test adapter.
        """
        module = "tvb_test.adapters.testadapter3"
        class_name = "TestAdapterHDDRequired"
        group = dao.find_group(module, class_name)
        adapter = FlowService().build_adapter_instance(group)
        output = adapter.get_output()
        output_type = output[0].__name__
        data = {"test": 100}
        TVBSettings.MAX_DISK_SPACE = float(
            adapter.get_required_disk_size(**data))
        tmp_folder = FilesHelper().get_project_folder(self.test_project,
                                                      "TEMP")
        self.operation_service.initiate_operation(
            self.test_user,
            self.test_project.id,
            adapter,
            tmp_folder,
            method_name=ABCAdapter.LAUNCH_METHOD,
            **data)
        dts = dao.get_values_of_datatype(self.test_project.id, Datatype2)
        self.assertEqual(len(dts), 1)
        datatype = dao.get_datatype_by_id(dts[0][0])
        self.assertEqual(datatype.subject, DataTypeMetaData.DEFAULT_SUBJECT,
                         "Wrong data stored.")
        self.assertEqual(datatype.type, output_type, "Wrong data stored.")

    def test_launch_operation_HDD_with_space_started_ops(self):
        """
        Test the actual operation flow by executing a test adapter.
        """
        space_taken_by_started = 100
        module = "tvb_test.adapters.testadapter3"
        class_name = "TestAdapterHDDRequired"
        group = dao.find_group(module, class_name)
        started_operation = model.Operation(
            self.test_user.id,
            self.test_project.id,
            group.id,
            "",
            status=model.STATUS_STARTED,
            result_disk_size=space_taken_by_started)
        dao.store_entity(started_operation)
        adapter = FlowService().build_adapter_instance(group)
        output = adapter.get_output()
        output_type = output[0].__name__
        data = {"test": 100}
        TVBSettings.MAX_DISK_SPACE = float(
            adapter.get_required_disk_size(**data) + space_taken_by_started)
        tmp_folder = FilesHelper().get_project_folder(self.test_project,
                                                      "TEMP")
        self.operation_service.initiate_operation(
            self.test_user,
            self.test_project.id,
            adapter,
            tmp_folder,
            method_name=ABCAdapter.LAUNCH_METHOD,
            **data)
        dts = dao.get_values_of_datatype(self.test_project.id, Datatype2)
        self.assertEqual(len(dts), 1)
        datatype = dao.get_datatype_by_id(dts[0][0])
        self.assertEqual(datatype.subject, DataTypeMetaData.DEFAULT_SUBJECT,
                         "Wrong data stored.")
        self.assertEqual(datatype.type, output_type, "Wrong data stored.")

    def test_launch_operation_HDD_full_space(self):
        """
        Test the actual operation flow by executing a test adapter.
        """
        module = "tvb_test.adapters.testadapter3"
        class_name = "TestAdapterHDDRequired"
        group = dao.find_group(module, class_name)
        adapter = FlowService().build_adapter_instance(group)
        data = {"test": 100}
        TVBSettings.MAX_DISK_SPACE = float(
            adapter.get_required_disk_size(**data) - 1)
        tmp_folder = FilesHelper().get_project_folder(self.test_project,
                                                      "TEMP")
        self.assertRaises(NoMemoryAvailableException,
                          self.operation_service.initiate_operation,
                          self.test_user,
                          self.test_project.id,
                          adapter,
                          tmp_folder,
                          method_name=ABCAdapter.LAUNCH_METHOD,
                          **data)
        dts = dao.get_values_of_datatype(self.test_project.id, Datatype2)
        self.assertEqual(len(dts), 0)

    def test_launch_operation_HDD_full_space_started_ops(self):
        """
        Test the actual operation flow by executing a test adapter.
        """
        space_taken_by_started = 100
        module = "tvb_test.adapters.testadapter3"
        class_name = "TestAdapterHDDRequired"
        group = dao.find_group(module, class_name)
        started_operation = model.Operation(
            self.test_user.id,
            self.test_project.id,
            group.id,
            "",
            status=model.STATUS_STARTED,
            result_disk_size=space_taken_by_started)
        dao.store_entity(started_operation)
        adapter = FlowService().build_adapter_instance(group)
        data = {"test": 100}
        TVBSettings.MAX_DISK_SPACE = float(
            adapter.get_required_disk_size(**data) + space_taken_by_started -
            1)
        tmp_folder = FilesHelper().get_project_folder(self.test_project,
                                                      "TEMP")
        self.assertRaises(NoMemoryAvailableException,
                          self.operation_service.initiate_operation,
                          self.test_user,
                          self.test_project.id,
                          adapter,
                          tmp_folder,
                          method_name=ABCAdapter.LAUNCH_METHOD,
                          **data)
        dts = dao.get_values_of_datatype(self.test_project.id, Datatype2)
        self.assertEqual(len(dts), 0)

    def test_stop_operation(self):
        """
        Test that an operation is successfully stopped.
        """
        module = "tvb_test.adapters.testadapter2"
        class_name = "TestAdapter2"
        group = dao.find_group(module, class_name)
        adapter = FlowService().build_adapter_instance(group)
        data = {"test": 5}
        algo_group = adapter.algorithm_group
        algo_category = dao.get_category_by_id(algo_group.fk_category)
        algo = dao.get_algorithm_by_group(algo_group.id)
        operations, _ = self.operation_service.prepare_operations(
            self.test_user.id, self.test_project.id, algo, algo_category, {},
            ABCAdapter.LAUNCH_METHOD, **data)
        self.operation_service._send_to_cluster(operations, adapter)
        self.operation_service.stop_operation(operations[0].id)
        operation = dao.get_operation_by_id(operations[0].id)
        self.assertEqual(operation.status, model.STATUS_CANCELED,
                         "Operation should have been canceled!")

    def test_stop_operation_finished(self):
        """
        Test that an operation that is already finished is not changed by the stop operation.
        """
        module = "tvb_test.adapters.testadapter1"
        class_name = "TestAdapter1"
        group = dao.find_group(module, class_name)
        adapter = FlowService().build_adapter_instance(group)
        data = {"test1_val1": 5, 'test1_val2': 5}
        algo_group = adapter.algorithm_group
        algo_category = dao.get_category_by_id(algo_group.fk_category)
        algo = dao.get_algorithm_by_group(algo_group.id)
        operations, _ = self.operation_service.prepare_operations(
            self.test_user.id, self.test_project.id, algo, algo_category, {},
            ABCAdapter.LAUNCH_METHOD, **data)
        self.operation_service._send_to_cluster(operations, adapter)
        operation = dao.get_operation_by_id(operations[0].id)
        operation.status = model.STATUS_FINISHED
        dao.store_entity(operation)
        self.operation_service.stop_operation(operations[0].id)
        operation = dao.get_operation_by_id(operations[0].id)
        self.assertEqual(operation.status, model.STATUS_FINISHED,
                         "Operation shouldn't have been canceled!")

    def test_array_from_string(self):
        """
        Simple test for parse array on 1d, 2d and 3d array.
        """
        row = {
            'description': 'test.',
            'default': 'None',
            'required': True,
            'label': 'test: ',
            'attributes': None,
            'quantifier': 'manual',
            'elementType': 'float',
            'type': 'array',
            'options': None,
            'name': 'test'
        }
        input_data_string = '[ [1 2 3] [4 5 6]]'
        output = string2array(input_data_string, ' ', row['elementType'])
        self.assertEqual(output.shape, (2, 3),
                         "Dimensions not properly parsed")
        for i in output[0]:
            self.assertTrue(i in [1, 2, 3])
        for i in output[1]:
            self.assertTrue(i in [4, 5, 6])
        input_data_string = '[1, 2, 3, 4, 5, 6]'
        output = string2array(input_data_string, ',', row['elementType'])
        self.assertEqual(output.shape, (6, ), "Dimensions not properly parsed")
        for i in output:
            self.assertTrue(i in [1, 2, 3, 4, 5, 6])
        input_data_string = '[ [ [1,1], [2, 2] ], [ [3 ,3], [4,4] ] ]'
        output = string2array(input_data_string, ',', row['elementType'])
        self.assertEqual(output.shape, (2, 2, 2), "Wrong dimensions.")
        for i in output[0][0]:
            self.assertTrue(i == 1)
        for i in output[0][1]:
            self.assertTrue(i == 2)
        for i in output[1][0]:
            self.assertTrue(i == 3)
        for i in output[1][1]:
            self.assertTrue(i == 4)
        row = {
            'description': 'test.',
            'default': 'None',
            'required': True,
            'label': 'test: ',
            'attributes': None,
            'quantifier': 'manual',
            'elementType': 'str',
            'type': 'array',
            'options': None,
            'name': 'test'
        }
        input_data_string = '[1, 2, 3, 4, 5, 6]'
        output = string2array(input_data_string, ',', row['elementType'])
        for i in output:
            self.assertTrue(i in [1, 2, 3, 4, 5, 6])

    def test_wrong_array_from_string(self):
        """Test that parsing an array from string is throwing the expected 
        exception when wrong input string"""
        row = {
            'description': 'test.',
            'default': 'None',
            'required': True,
            'label': 'test: ',
            'attributes': None,
            'quantifier': 'manual',
            'elementType': 'float',
            'type': 'array',
            'options': None,
            'name': 'test'
        }
        input_data_string = '[ [1,2 3] [4,5,6]]'
        self.assertRaises(ValueError, string2array, input_data_string, ',',
                          row['elementType'])
        input_data_string = '[ [1,2,wrong], [4, 5, 6]]'
        self.assertRaises(ValueError, string2array, input_data_string, ',',
                          row['elementType'])
        row = {
            'description': 'test.',
            'default': 'None',
            'required': True,
            'label': 'test: ',
            'attributes': None,
            'quantifier': 'manual',
            'elementType': 'str',
            'type': 'array',
            'options': None,
            'name': 'test'
        }
        output = string2array(input_data_string, ',', row['elementType'])
        self.assertEqual(output.shape, (2, 3))
        self.assertEqual(output[0][2], 'wrong',
                         'String data not converted properly')
        input_data_string = '[ [1,2 3] [4,5,6]]'
        output = string2array(input_data_string, ',', row['elementType'])
        self.assertEqual(output[0][1], '2 3')

    def test_reduce_dimension_component(self):
        """
         This method tests if the data passed to the launch method of
         the NDimensionArrayAdapter adapter is correct. The passed data should be a list
         of arrays with one dimension.
        """
        inserted_data = FlowService().get_available_datatypes(
            self.test_project.id, "tvb.datatypes.arrays.MappedArray")
        self.assertEqual(len(inserted_data), 0, "Expected to find no data.")
        #create an operation
        algorithm_id = FlowService().get_algorithm_by_module_and_class(
            'tvb_test.adapters.ndimensionarrayadapter',
            'NDimensionArrayAdapter')[0].id
        operation = model.Operation(self.test_user.id,
                                    self.test_project.id,
                                    algorithm_id,
                                    'test params',
                                    meta=json.dumps(
                                        {DataTypeMetaData.KEY_STATE: "RAW"}),
                                    status=model.STATUS_FINISHED,
                                    method_name=ABCAdapter.LAUNCH_METHOD)
        operation = dao.store_entity(operation)
        #save the array wrapper in DB
        adapter_instance = NDimensionArrayAdapter()
        PARAMS = {}
        self.operation_service.initiate_prelaunch(operation, adapter_instance,
                                                  {}, **PARAMS)
        inserted_data = FlowService().get_available_datatypes(
            self.test_project.id, "tvb.datatypes.arrays.MappedArray")
        self.assertEqual(len(inserted_data), 1, "Problems when inserting data")
        gid = inserted_data[0][2]
        entity = dao.get_datatype_by_gid(gid)
        #from the 3D array do not select any array
        PARAMS = {
            "python_method": "reduce_dimension",
            "input_data": gid,
            "input_data_dimensions_0": "requiredDim_1",
            "input_data_dimensions_1": "",
            "input_data_dimensions_2": ""
        }
        try:
            self.operation_service.initiate_prelaunch(operation,
                                                      adapter_instance, {},
                                                      **PARAMS)
            self.fail(
                "Test should not pass. The resulted array should be a 1D array."
            )
        except Exception:
            # OK, do nothing; we were expecting to produce a 1D array
            pass
        #from the 3D array select only a 1D array
        first_dim = [gid + '_1_0', 'requiredDim_1']
        PARAMS = {
            "python_method": "reduce_dimension",
            "input_data": gid,
            "input_data_dimensions_0": first_dim,
            "input_data_dimensions_1": gid + "_2_1"
        }
        self.operation_service.initiate_prelaunch(operation, adapter_instance,
                                                  {}, **PARAMS)
        expected_result = entity.array_data[:, 0, 1]
        actual_result = adapter_instance.launch_param
        self.assertEqual(len(actual_result), len(expected_result),
                         "Not the same size for results!")
        self.assertTrue(numpy.equal(actual_result, expected_result).all())

        #from the 3D array select a 2D array
        first_dim = [gid + '_1_0', gid + '_1_1', 'requiredDim_2']
        PARAMS = {
            "python_method": "reduce_dimension",
            "input_data": gid,
            "input_data_dimensions_0": first_dim,
            "input_data_dimensions_1": gid + "_2_1"
        }
        self.operation_service.initiate_prelaunch(operation, adapter_instance,
                                                  {}, **PARAMS)
        expected_result = entity.array_data[slice(0, None), [0, 1], 1]
        actual_result = adapter_instance.launch_param
        self.assertEqual(len(actual_result), len(expected_result),
                         "Not the same size for results!")
        self.assertTrue(numpy.equal(actual_result, expected_result).all())

        #from 3D array select 1D array by applying SUM function on the first
        #dimension and average function on the second dimension
        PARAMS = {
            "python_method": "reduce_dimension",
            "input_data": gid,
            "input_data_dimensions_0": ["requiredDim_1", "func_sum"],
            "input_data_dimensions_1": "func_average",
            "input_data_dimensions_2": ""
        }
        self.operation_service.initiate_prelaunch(operation, adapter_instance,
                                                  {}, **PARAMS)
        aux = numpy.sum(entity.array_data, axis=0)
        expected_result = numpy.average(aux, axis=0)
        actual_result = adapter_instance.launch_param
        self.assertEqual(len(actual_result), len(expected_result),
                         "Not the same size of results!")
        self.assertTrue(numpy.equal(actual_result, expected_result).all())

        #from 3D array select a 2D array and apply op. on the second dimension
        PARAMS = {
            "python_method":
            "reduce_dimension",
            "input_data":
            gid,
            "input_data_dimensions_0": [
                "requiredDim_2", "func_sum", "expected_shape_x,512",
                "operations_x,>"
            ],
            "input_data_dimensions_1":
            "",
            "input_data_dimensions_2":
            ""
        }
        try:
            self.operation_service.initiate_prelaunch(operation,
                                                      adapter_instance, {},
                                                      **PARAMS)
            self.fail(
                "Test should not pass! The second dimension of the array should be >512."
            )
        except Exception:
            # OK, do nothing;
            pass
Example #2
0
class FlowContollerTest(BaseControllersTest):
    """ Unit tests for flowcontoller """
    
    def setUp(self):
        """
        Sets up the environment for testing;
        creates a `FlowController`
        """
        BaseControllersTest.init(self)
        self.flow_c =  FlowController()
        self.burst_c = BurstController()
        self.operation_service = OperationService()
    
    
    def tearDown(self):
        """ Cleans up the testing environment """
        BaseControllersTest.cleanup(self)
        self.reset_database()
            
            
    def test_context_selected(self):
        """
        Remove the project from cherrypy session and check that you are
        redirected to projects page.
        """
        del cherrypy.session[b_c.KEY_PROJECT]
        self._expect_redirect('/project/viewall', self.flow_c.step)
    

    def test_invalid_step(self):
        """
        Pass an invalid step and make sure we are redirected to tvb start page.
        """
        self._expect_redirect('/tvb', self.flow_c.step)
        
        
    def test_valid_step(self):
        """
        For all algorithm categories check that a submenu is generated and the result
        page has it's title given by category name.
        """
        categories = dao.get_algorithm_categories()
        for categ in categories:
            result_dict = self.flow_c.step(categ.id)
            self.assertTrue(b_c.KEY_SUBMENU_LIST in result_dict, 
                            "Expect to have a submenu with available algorithms for category.")
            self.assertEqual(result_dict["section_name"], categ.displayname.lower())


    def test_step_connectivity(self):
        """
        Check that the correct section name and connectivity submenu are returned for the 
        connectivity step.
        """
        result_dict = self.flow_c.step_connectivity()
        self.assertEqual(result_dict['section_name'], 'connectivity')
        self.assertEqual(result_dict['submenu_list'], self.flow_c.connectivity_submenu)


    def test_default(self):
        """
        Test default method from step controllers. Check that the submit link is ok, that a mainContent
        is present in result dict and that the isAdapter flag is set to true.
        """
        cherrypy.request.method = "GET"
        categories = dao.get_algorithm_categories()
        for categ in categories:
            algo_groups = dao.get_groups_by_categories([categ.id])
            for algo in algo_groups:
                result_dict = self.flow_c.default(categ.id, algo.id)
                self.assertEqual(result_dict[b_c.KEY_SUBMIT_LINK], '/flow/%i/%i'%(categ.id, algo.id))
                self.assertTrue('mainContent' in result_dict)
                self.assertTrue(result_dict['isAdapter'])
                
                
    def test_default_cancel(self):
        """
        On cancel we should get a redirect to the back page link.
        """
        cherrypy.request.method = "POST"
        categories = dao.get_algorithm_categories()
        algo_groups = dao.get_groups_by_categories([categories[0].id])
        self._expect_redirect('/project/viewoperations/%i'%(self.test_project.id), 
                              self.flow_c.default, categories[0].id, algo_groups[0].id, 
                              cancel=True, back_page='operations')
        
        
    def test_default_invalid_key(self):
        """
        Pass invalid keys for adapter and step and check you get redirect to tvb entry
        page with error set.
        """
        self._expect_redirect('/tvb?error=True', self.flow_c.default, 'invalid', 'invalid')
        
        
    def test_read_datatype_attribute(self):
        """
        Read an attribute from a datatype.
        """
        dt = DatatypesFactory().create_datatype_with_storage("test_subject", "RAW_STATE", 'this is the stored data'.split())
        returned_data = self.flow_c.read_datatype_attribute(dt.gid, "string_data")
        self.assertEqual(returned_data, '["this", "is", "the", "stored", "data"]')
        
        
    def test_read_datatype_attribute_method_call(self):
        """
        Call method on given datatype.
        """
        dt = DatatypesFactory().create_datatype_with_storage("test_subject", "RAW_STATE", 'this is the stored data'.split())
        args = {'length' : 101}
        returned_data = self.flow_c.read_datatype_attribute(dt.gid, 'return_test_data', **args)
        self.assertTrue(returned_data == str(range(101)))
        
        
    def test_get_simple_adapter_interface(self):
        adapter = dao.find_group('tvb_test.adapters.testadapter1', 'TestAdapter1')
        result = self.flow_c.get_simple_adapter_interface(adapter.id)
        expected_interface = TestAdapter1().get_input_tree()
        self.assertEqual(result['inputList'], expected_interface)
        
    
    def _long_burst_launch(self, is_range=False):
        self.burst_c.index()
        connectivity = DatatypesFactory().create_connectivity()[1]
        launch_params = copy.deepcopy(SIMULATOR_PARAMETERS)
        launch_params['connectivity'] = dao.get_datatype_by_id(connectivity.id).gid
        if not is_range:
            launch_params['simulation_length'] = '10000'
        else:
            launch_params['simulation_length'] = '[10000,10001,10002]'
            launch_params['first_range'] = 'simulation_length'
        burst_id, _ = json.loads(self.burst_c.launch_burst("new", "test_burst", **launch_params))
        return dao.get_burst_by_id(burst_id)
        
            
    def test_stop_burst_operation(self):
        burst_config = self._long_burst_launch()
        waited = 1
        timeout = 50
        operations = dao.get_operations_in_burst(burst_config.id)
        while not len(operations) and waited <= timeout:
            sleep(1)
            waited += 1
            operations = dao.get_operations_in_burst(burst_config.id)
        operation = dao.get_operations_in_burst(burst_config.id)[0]
        self.assertEqual(operation.status, model.STATUS_STARTED)
        self.flow_c.stop_burst_operation(operation.id, 0, False)
        operation = dao.get_operation_by_id(operation.id)
        self.assertEqual(operation.status, model.STATUS_CANCELED)
        
        
    def test_stop_burst_operation_group(self):
        burst_config = self._long_burst_launch(True)
        waited = 1
        timeout = 50
        operations = dao.get_operations_in_burst(burst_config.id)
        while not len(operations) and waited <= timeout:
            sleep(1)
            waited += 1
            operations = dao.get_operations_in_burst(burst_config.id)
        operations = dao.get_operations_in_burst(burst_config.id)
        for operation in operations:
            self.assertEqual(operation.status, model.STATUS_STARTED)
        self.flow_c.stop_burst_operation(operation.fk_operation_group, 1, False)
        for operation in operations:
            operation = dao.get_operation_by_id(operation.id)
            self.assertEqual(operation.status, model.STATUS_CANCELED)
        
        
    def test_remove_burst_operation(self):
        burst_config = self._long_burst_launch()
        waited = 1
        timeout = 50
        operations = dao.get_operations_in_burst(burst_config.id)
        while not len(operations) and waited <= timeout:
            sleep(1)
            waited += 1
            operations = dao.get_operations_in_burst(burst_config.id)
        operation = dao.get_operations_in_burst(burst_config.id)[0]
        self.assertEqual(operation.status, model.STATUS_STARTED)
        self.flow_c.stop_burst_operation(operation.id, 0, True)
        operation = dao.get_operation_by_id(operation.id)
        self.assertTrue(operation is None)
        
        
    def test_remove_burst_operation_group(self):
        burst_config = self._long_burst_launch(True)
        waited = 1
        timeout = 50
        operations = dao.get_operations_in_burst(burst_config.id)
        while not len(operations) and waited <= timeout:
            sleep(1)
            waited += 1
            operations = dao.get_operations_in_burst(burst_config.id)
        operations = dao.get_operations_in_burst(burst_config.id)
        for operation in operations:
            self.assertEqual(operation.status, model.STATUS_STARTED)
        self.flow_c.stop_burst_operation(operation.fk_operation_group, 1, True)
        for operation in operations:
            operation = dao.get_operation_by_id(operation.id)
            self.assertTrue(operation is None)
            
            
    def test_stop_operations(self):
        module = "tvb_test.adapters.testadapter1"
        class_name = "TestAdapter1"
        group = dao.find_group(module, class_name)
        adapter = FlowService().build_adapter_instance(group)
        data = {"test1_val1": 5, 'test1_val2': 5}
        algo_group = adapter.algorithm_group
        algo_category = dao.get_category_by_id(algo_group.fk_category)
        algo = dao.get_algorithm_by_group(algo_group.id)
        operations, _ = self.operation_service.prepare_operations(self.test_user.id, self.test_project.id, algo,
                                                                  algo_category, {}, ABCAdapter.LAUNCH_METHOD, **data)
        self.operation_service._send_to_cluster(operations, adapter)
        operation = dao.get_operation_by_id(operations[0].id)
        self.assertEqual(operation.status, model.STATUS_STARTED)
        self.flow_c.stop_operation(operation.id, 0, False)
        operation = dao.get_operation_by_id(operation.id)
        self.assertEqual(operation.status, model.STATUS_CANCELED)
        
        
    def test_stop_operations_group(self):
        module = "tvb_test.adapters.testadapter1"
        class_name = "TestAdapter1"
        group = dao.find_group(module, class_name)
        adapter = FlowService().build_adapter_instance(group)
        data = {'first_range' : "test1_val1", "test1_val1": '5,6,7', 'test1_val2': 5}
        algo_group = adapter.algorithm_group
        algo_category = dao.get_category_by_id(algo_group.fk_category)
        algo = dao.get_algorithm_by_group(algo_group.id)
        operations, _ = self.operation_service.prepare_operations(self.test_user.id, self.test_project.id, algo,
                                                                  algo_category, {}, ABCAdapter.LAUNCH_METHOD, **data)
        self.operation_service._send_to_cluster(operations, adapter)
        for operation in operations:
            operation = dao.get_operation_by_id(operation.id)
            self.assertEqual(operation.status, model.STATUS_STARTED)
        self.flow_c.stop_operation(operation.fk_operation_group, 1, False)
        for operation in operations:
            operation = dao.get_operation_by_id(operation.id)
            self.assertEqual(operation.status, model.STATUS_CANCELED)