Example #1
0
    def _land_cover(self, model_run, values, errors):
        land_cover_controller_helper = LandCoverControllerHelper()
        if not request.POST:
            self._user_service.set_current_model_run_creation_action(self.current_user, "land_cover")
            land_cover_controller_helper.add_land_covers_to_context(c, errors, model_run)
            if len(errors) > 0:
                helpers.error_flash(errors['land_cover_actions'])
            return render('model_run/land_cover.html')

        else:
            land_cover_controller_helper.save_land_cover_actions(values, errors, model_run)
            if len(errors) > 0:
                helpers.error_flash(errors['land_cover_actions'])
                return render('model_run/land_cover.html')
            else:
                # Get the action to perform
                self._model_run_controller_helper.check_user_quota(self.current_user)
                try:
                    action = values['submit']
                except KeyError:
                    action = None
                if action == u'Next':
                    redirect(url(controller='model_run', action='output'))
                else:
                    redirect(url(controller='model_run', action='extents'))
class TestLandCoverControllerHelper(BaseTest):
    def setUp(self):
        driving_data = DrivingDataset()
        driving_data.name = "Driving1"
        driving_data.id = 1

        self.return_dd_id = 10

        self.model_run = ModelRun()
        self.model_run.name = "Model Run1"
        self.model_run.driving_dataset = driving_data
        self.model_run.driving_dataset_id = 1

        self.land_cover_service = LandCoverService()
        self.land_cover_service.get_land_cover_region_by_id = self._mock_lcs_get_land_cover_region
        self.land_cover_service.get_land_cover_values = self._mock_get_land_cover_values
        self.land_cover_service.get_land_cover_categories = self._mock_get_land_cover_categories
        self.land_cover_service.save_land_cover_actions_for_model = MagicMock()
        self.land_cover_service.get_land_cover_actions_for_model = self._mock_lcs_get_actions_for_model_run
        self.land_cover_service.save_fractional_land_cover_for_model = MagicMock()
        self.land_cover_service.get_default_fractional_cover = self._mock_lcs_get_default_fractional_cover
        self.land_cover_service.save_default_soil_properties = MagicMock()

        self.land_cover_helper = LandCoverControllerHelper(land_cover_service=self.land_cover_service)

    class Context(object):
        """
        Mock context object
        """

        pass

    @staticmethod
    def _mock_get_land_cover_values(model_run, return_ice=False):
        land_cover_values = []
        types = {1: "BT", 2: "NT", 3: "C3G", 4: "C4G", 5: "Shrub", 6: "Urban", 7: "Lake", 8: "Soil", 9: "Ice"}
        for index in types:
            land_cover_value = LandCoverValue()
            land_cover_value.id = index
            land_cover_value.index = index
            land_cover_value.name = types[index]
            land_cover_values.append(land_cover_value)
        return land_cover_values

    @staticmethod
    def _mock_get_land_cover_categories(driving_data_id):
        cat1 = LandCoverRegionCategory()
        cat1.driving_dataset_id = driving_data_id
        cat1.name = "Rivers"
        cat1.id = 1

        region1 = LandCoverRegion()
        region1.id = 1
        region1.name = "Thames"
        region1.category_id = 1
        region1.category = cat1

        region2 = LandCoverRegion()
        region2.id = 2
        region2.name = "Itchen"
        region2.category_id = 1
        region2.category = cat1

        cat1.regions = [region1, region2]

        cat2 = LandCoverRegionCategory()
        cat2.driving_dataset_id = driving_data_id
        cat2.name = "Counties"
        cat2.id = 2

        region3 = LandCoverRegion()
        region3.id = 3
        region3.name = "Hampshire"
        region3.category_id = 2
        region3.category = cat2

        region4 = LandCoverRegion()
        region4.id = 4
        region4.name = "Oxfordshire"
        region4.category_id = 2
        region4.category = cat2

        cat2.regions = [region3, region4]

        return [cat1, cat2]

    @staticmethod
    def _mock_lcs_get_land_cover_region(id):
        dds = DrivingDataset()
        dds.id = 1

        land_cover_type = LandCoverRegionCategory()
        land_cover_type.id = 1
        land_cover_type.driving_dataset_id = 1
        land_cover_type.driving_dataset = dds

        land_cover_region = LandCoverRegion()
        land_cover_region.id = id
        land_cover_region.name = "Sand"
        land_cover_region.category = land_cover_type

        return land_cover_region

    @staticmethod
    def _mock_lcs_get_land_cover_region_wrong_dataset(id):
        dds = DrivingDataset()
        dds.id = 7

        land_cover_type = LandCoverRegionCategory()
        land_cover_type.id = 1
        land_cover_type.driving_dataset_id = 7
        land_cover_type.driving_dataset = dds

        land_cover_region = LandCoverRegion()
        land_cover_region.id = id
        land_cover_region.name = "Sand"
        land_cover_region.category = land_cover_type

        return land_cover_region

    @staticmethod
    def _mock_lcs_get_actions_for_model_run(model_run):
        cat = LandCoverRegionCategory()
        cat.id = 1
        cat.name = "Countries"
        cat.driving_dataset_id = 1

        region = LandCoverRegion()
        region.id = 1
        region.name = "Wales"
        region.category = cat

        action = LandCoverAction()
        action.id = 1
        action.region = region
        action.value_id = 1

        return [action]

    @staticmethod
    def _mock_lcs_get_actions_for_model_run_wrong_dataset(model_run):
        cat = LandCoverRegionCategory()
        cat.id = 1
        cat.name = "Countries"
        cat.driving_dataset_id = 2

        region = LandCoverRegion()
        region.id = 1
        region.name = "Wales"
        region.category = cat

        action = LandCoverAction()
        action.id = 1
        action.region = region
        action.value_id = 1

        return [action]

    @staticmethod
    def _mock_lcs_get_actions_for_model_run_no_actions(model_run, user):
        return []

    @staticmethod
    def _mock_lcs_get_default_fractional_cover(model_run, user):
        return [0.02, 0.11, 0.02, 0.05, 0.35, 0.19, 0.22, 0.04, 0.0]

    @staticmethod
    def _mock_lcs_get_awkward_default_fractional_cover(model_run, user):
        return [0.0102193951607, 0.0, 0.361101979017, 0.0344029143453, 0.0, 0.369327515364, 0.0, 0.124948188663, 0.0]

    @staticmethod
    def _mock_lcs_get_missing_default_fractional_cover(model_run, user):
        return 9 * [-9999.99]

    def test_GIVEN_single_action_WHEN_save_land_cover_THEN_land_cover_action_saved(self):
        values = {"action_1_region": u"1", "action_1_value": u"8", "action_1_order": u"1"}
        self.land_cover_helper.save_land_cover_actions(values, {}, self.model_run)
        called_land_cover_actions = self.land_cover_service.save_land_cover_actions_for_model.call_args[0][1]

        lca1 = called_land_cover_actions[0]
        assert_that(lca1.region_id, is_(1))
        assert_that(lca1.value_id, is_(8))

    def test_GIVEN_two_actions_WHEN_save_land_cover_THEN_both_saved_with_correct_order(self):
        values = {
            "action_1_region": u"1",
            "action_1_value": u"8",
            "action_1_order": u"1",
            "action_2_region": u"3",
            "action_2_value": u"7",
            "action_2_order": u"2",
        }
        self.land_cover_helper.save_land_cover_actions(values, {}, self.model_run)
        called_land_cover_actions = self.land_cover_service.save_land_cover_actions_for_model.call_args[0][1]

        lca1 = called_land_cover_actions[0]
        assert_that(lca1.region_id, is_(1))
        assert_that(lca1.value_id, is_(8))
        assert_that(lca1.order, is_(1))

        lca2 = called_land_cover_actions[1]
        assert_that(lca2.region_id, is_(3))
        assert_that(lca2.value_id, is_(7))
        assert_that(lca2.order, is_(2))

    def test_GIVEN_invalid_region_WHEN_save_land_cover_THEN_error_returned(self):
        # In this test, the region is for another dataset
        self.land_cover_service.get_land_cover_region_by_id = self._mock_lcs_get_land_cover_region_wrong_dataset

        values = {"action_1_region": u"10", "action_1_value": u"8", "action_1_order": u"1"}
        errors = {}
        self.land_cover_helper.save_land_cover_actions(values, errors, self.model_run)

        assert_that(len(errors), is_(1))

    def test_GIVEN_invalid_region_WHEN_save_land_cover_THEN_land_covers_not_saved(self):
        # In this test, the region is for another dataset
        self.land_cover_service.get_land_cover_region_by_id = self._mock_lcs_get_land_cover_region_wrong_dataset

        values = {"action_1_region": u"10", "action_1_value": u"8", "action_1_order": u"1"}
        errors = {}
        self.land_cover_helper.save_land_cover_actions(values, errors, self.model_run)

        assert not self.land_cover_service.save_land_cover_actions_for_model.called

    def test_GIVEN_invalid_land_cover_value_WHEN_save_land_cover_THEN_error_returned(self):
        # In this test, the land cover value doesn't exist
        values = {"action_1_region": u"1", "action_1_value": u"77", "action_1_order": u"1"}
        errors = {}
        self.land_cover_helper.save_land_cover_actions(values, errors, self.model_run)

        assert_that(len(errors), is_(1))

    def test_GIVEN_invalid_land_cover_value_WHEN_save_land_cover_THEN_land_covers_not_saved(self):
        # In this test, the land cover value doesn't exist
        values = {"action_1_region": u"1", "action_1_value": u"77", "action_1_order": u"1"}
        errors = {}
        self.land_cover_helper.save_land_cover_actions(values, errors, self.model_run)

        assert not self.land_cover_service.save_land_cover_actions_for_model.called

    def test_GIVEN_valid_values_WHEN_save_fractional_land_cover_THEN_values_saved_to_file(self):
        values = {
            "submit": u"Next",
            "fractional_cover": u"1",
            "land_cover_value_1": u"20",
            "land_cover_value_2": u"20",
            "land_cover_value_3": u"10",
            "land_cover_value_4": u"10",
            "land_cover_value_5": u"10",
            "land_cover_value_6": u"10",
            "land_cover_value_7": u"10",
            "land_cover_value_8": u"10",
        }
        errors = {}

        self.land_cover_helper.save_fractional_land_cover(values, errors, self.model_run, User())
        assert_that(len(errors), is_(0))

        called_save_frac_cover = self.land_cover_service.save_fractional_land_cover_for_model.call_args_list[0][0][1]
        assert_that(called_save_frac_cover, is_("0.2\t0.2\t0.1\t0.1\t0.1\t0.1\t0.1\t0.1\t0"))

    def test_GIVEN_values_dont_add_up_WHEN_save_fractional_land_cover_THEN_error_and_values_not_saved_to_file(self):
        values = {
            "submit": u"Next",
            "fractional_cover": u"1",
            "land_cover_value_1": u"20",
            "land_cover_value_2": u"25",
            "land_cover_value_3": u"10",
            "land_cover_value_4": u"10",
            "land_cover_value_5": u"10",
            "land_cover_value_6": u"10",
            "land_cover_value_7": u"10",
            "land_cover_value_8": u"15",
        }
        errors = {}

        self.land_cover_helper.save_fractional_land_cover(values, errors, self.model_run, User())
        assert_that(errors["land_cover_frac"], is_("The sum of all the land cover fractions must be 100%"))

        assert not self.land_cover_service.save_fractional_land_cover_for_model.called

    def test_GIVEN_empty_values_WHEN_save_fractional_land_cover_THEN_error_returned(self):
        values = {
            "submit": u"Next",
            "fractional_cover": u"1",
            "land_cover_value_1": u"20",
            "land_cover_value_2": u"25",
            "land_cover_value_3": u"10",
            "land_cover_value_4": u"",
            "land_cover_value_5": u"10",
            "land_cover_value_6": u"10",
            "land_cover_value_7": u"10",
            "land_cover_value_8": u"15",
        }
        errors = {}

        self.land_cover_helper.save_fractional_land_cover(values, errors, self.model_run, User())
        assert_that(errors["land_cover_value_4"], is_("Please enter a number"))

        assert not self.land_cover_service.save_fractional_land_cover_for_model.called

    def test_GIVEN_negative_value_WHEN_save_fractional_land_cover_THEN_error_returned(self):
        values = {
            "submit": u"Next",
            "fractional_cover": u"1",
            "land_cover_value_1": u"20",
            "land_cover_value_2": u"20",
            "land_cover_value_3": u"20",
            "land_cover_value_4": u"-25",
            "land_cover_value_5": u"20",
            "land_cover_value_6": u"20",
            "land_cover_value_7": u"10",
            "land_cover_value_8": u"15",
        }
        errors = {}

        self.land_cover_helper.save_fractional_land_cover(values, errors, self.model_run, User())
        assert_that(errors["land_cover_value_4"], is_("Please enter a positive number"))

        assert not self.land_cover_service.save_fractional_land_cover_for_model.called

    def test_GIVEN_ice_chosen_WHEN_save_fractional_land_cover_THEN_values_saved_to_file(self):
        values = {"submit": u"Next", "land_cover_ice": u"1"}
        errors = {}

        self.land_cover_helper.save_fractional_land_cover(values, errors, self.model_run, User())
        assert_that(len(errors), is_(0))

        called_save_frac_cover = self.land_cover_service.save_fractional_land_cover_for_model.call_args_list[0][0][1]
        assert_that(called_save_frac_cover, is_("0\t0\t0\t0\t0\t0\t0\t0\t1"))

    def test_GIVEN_no_land_cover_actions_saved_WHEN_add_to_context_THEN_no_errors_returned(self):
        self.land_cover_service.save_land_cover_actions_for_model = self._mock_lcs_get_actions_for_model_run
        errors = {}
        self.land_cover_helper.add_land_covers_to_context(self.Context(), errors, self.model_run)
        assert_that(len(errors), is_(0))

    def test_GIVEN_driving_data_has_categories_WHEN_add_to_context_THEN_context_contains_land_cover_categories(self):
        context = self.Context()
        self.land_cover_helper.add_land_covers_to_context(context, {}, self.model_run)

        assert_that(len(context.land_cover_categories), is_(2))

    def test_GIVEN_nothing_saved_WHEN_add_to_context_THEN_context_contains_land_cover_values(self):
        context = self.Context()
        self.land_cover_helper.add_land_covers_to_context(context, {}, self.model_run)

        assert_that(len(context.land_cover_values), is_(9))

    def test_GIVEN_land_cover_actions_saved_WHEN_add_to_context_THEN_context_contains_actions(self):
        context = self.Context()
        self.land_cover_helper.add_land_covers_to_context(context, {}, self.model_run)

        assert_that(len(context.land_cover_actions), is_(1))

    def test_GIVEN_invalid_land_cover_actions_saved_WHEN_add_to_context_THEN_errors_returned(self):
        self.land_cover_service.get_land_cover_actions_for_model = (
            self._mock_lcs_get_actions_for_model_run_wrong_dataset
        )
        errors = {}
        self.land_cover_helper.add_land_covers_to_context(self.Context(), errors, self.model_run)

        assert_that(len(errors), is_(1))

    def test_GIVEN_invalid_land_cover_actions_saved_WHEN_add_to_context_THEN_no_actions_returned(self):
        self.land_cover_service.get_land_cover_actions_for_model = (
            self._mock_lcs_get_actions_for_model_run_wrong_dataset
        )

        context = self.Context()
        self.land_cover_helper.add_land_covers_to_context(context, {}, self.model_run)

        assert_that(len(context.land_cover_actions), is_(0))

    def test_GIVEN_nothing_WHEN_add_fractional_cover_to_context_THEN_cover_types_added(self):
        self.model_run.land_cover_frac = "0\t0\t0\t0\t0\t0\t0\t0\t1"

        context = self.Context()
        self.land_cover_helper.add_fractional_land_cover_to_context(context, {}, self.model_run, User())

        assert_that(len(context.land_cover_values), is_(9))

    def test_GIVEN_fractional_land_cover_saved_WHEN_add_fractional_cover_to_context_THEN_cover_values_added(self):
        self.model_run.land_cover_frac = "0\t0\t0\t0\t0\t0\t0\t0\t1"

        context = self.Context()
        self.land_cover_helper.add_fractional_land_cover_to_context(context, {}, self.model_run, User())

        assert_that(len(context.land_cover_values), is_(9))
        assert_that(context.land_cover_values["land_cover_ice"], is_(1))

    def test_GIVEN_nothing_WHEN_add_fractional_cover_to_context_THEN_ice_index_added(self):
        self.model_run.land_cover_frac = "0\t0\t0\t0\t0\t0\t0\t0\t1"

        context = self.Context()
        self.land_cover_helper.add_fractional_land_cover_to_context(context, {}, self.model_run, User())

        assert_that(context.ice_index, is_(9))

    def test_GIVEN_no_fractional_land_cover_saved_WHEN_add_fractional_cover_to_context_THEN_defaults_returned(self):
        context = self.Context()
        self.land_cover_helper.add_fractional_land_cover_to_context(context, {}, self.model_run, User())
        context_vals = [context.land_cover_values[key] for key in sorted(context.land_cover_values)]
        assert_that(context_vals, is_([2.0, 11.0, 2.0, 5.0, 35.0, 19.0, 22.0, 4.0]))

    def test_GIVEN_awkward_default_fractional_cover_WHEN_add_cover_to_context_THEN_truncated_and_adds_to_one(self):
        # Sometimes the default fractional cover retrieved from the netCDF file is awkward in that the
        # fractions are long (11 decimal places) and don't add up to precisely 1.0
        self.land_cover_service.get_default_fractional_cover = self._mock_lcs_get_awkward_default_fractional_cover

        context = self.Context()
        self.land_cover_helper.add_fractional_land_cover_to_context(context, {}, self.model_run, User())
        context_vals = [
            context.land_cover_values[key] for key in sorted(context.land_cover_values) if "land_cover_value" in key
        ]
        assert sum(context_vals) - 100.0 < 0.00000001

    def test_GIVEN_missing_fractional_cover_WHEN_add_cover_to_context_THEN_zeros_returned(self):
        self.land_cover_service.get_default_fractional_cover = self._mock_lcs_get_missing_default_fractional_cover

        context = self.Context()
        self.land_cover_helper.add_fractional_land_cover_to_context(context, {}, self.model_run, User())
        for value in context.land_cover_values.values():
            assert_that(value, is_(0.0))