class PayloadBaseInterfaceTestCase(unittest.TestCase):
    def setUp(self):
        self.module = DNFModule()
        self.interface = DNFInterface(self.module)

        self.shared_tests = PayloadSharedTest(self,
                                              payload=self.module,
                                              payload_intf=self.interface)

    def type_test(self):
        self.shared_tests.check_type(PayloadType.DNF)

    def required_space_test(self):
        """Test required space."""
        self.module._required_space = 100

        self.assertEqual(self.interface.RequiredSpace, 100)

    def required_default_space_test(self):
        """Test default value for required space.

        This is used when space is not known.
        """
        self.module._required_space = None

        self.assertEqual(self.interface.RequiredSpace,
                         self.module.default_required_space)

    @patch.object(DNFModule, "supported_source_types", [SourceType.URL])
    def supported_sources_test(self):
        """Test supported sources API."""
        self.assertEqual([SourceType.URL.value],
                         self.interface.SupportedSourceTypes)

    def sources_empty_test(self):
        """Test sources API for emptiness."""
        self.shared_tests.check_empty_sources()

    @patch.object(DNFModule, "supported_source_types", [SourceType.URL])
    @patch_dbus_publish_object
    def set_source_test(self, publisher):
        """Test if set source API payload."""
        sources = [self.shared_tests.prepare_source(SourceType.URL)]

        self.shared_tests.set_and_check_sources(sources)

    @patch.object(DNFModule, "supported_source_types", [SourceType.URL])
    @patch_dbus_publish_object
    def add_source_test(self, publisher):
        """Test module API to add source."""
        source1 = self.shared_tests.prepare_source(SourceType.URL,
                                                   SourceState.NOT_APPLICABLE)

        sources = [source1]
        self.shared_tests.set_and_check_sources(sources)

        source2 = self.shared_tests.prepare_source(SourceType.URL)
        self.module.add_source(source2)

        sources.append(source2)
        self.shared_tests.check_sources(sources)

    @patch.object(DNFModule, "supported_source_types", [SourceType.URL])
    @patch_dbus_publish_object
    def add_source_incompatible_source_failed_test(self, publisher):
        """Test module API to add source failed with incompatible source."""
        source1 = self.shared_tests.prepare_source(SourceType.URL,
                                                   SourceState.NOT_APPLICABLE)

        sources = [source1]
        self.shared_tests.set_and_check_sources(sources)

        source2 = self.shared_tests.prepare_source(SourceType.NFS)
        with self.assertRaises(IncompatibleSourceError):
            self.module.add_source(source2)

        self.shared_tests.check_sources(sources)

    @patch.object(DNFModule, "supported_source_types", [SourceType.URL])
    @patch_dbus_publish_object
    def add_source_ready_failed_test(self, publisher):
        """Test module API to add source failed with ready source."""
        source1 = self.shared_tests.prepare_source(SourceType.URL,
                                                   SourceState.READY)

        sources = [source1]
        self.shared_tests.set_and_check_sources(sources)

        source2 = self.shared_tests.prepare_source(SourceType.URL)
        with self.assertRaises(SourceSetupError):
            self.module.add_source(source2)

        self.shared_tests.check_sources(sources)

    @patch.object(DNFModule, "supported_source_types",
                  [SourceType.URL, SourceType.NFS])
    @patch_dbus_publish_object
    def set_multiple_source_test(self, publisher):
        """Test payload setting multiple compatible sources."""
        sources = [
            self.shared_tests.prepare_source(SourceType.NFS),
            self.shared_tests.prepare_source(SourceType.URL),
            self.shared_tests.prepare_source(SourceType.URL),
        ]

        self.shared_tests.set_and_check_sources(sources)

    @patch.object(DNFModule, "supported_source_types", [SourceType.URL])
    @patch_dbus_publish_object
    def set_incompatible_source_test(self, publisher):
        """Test payload setting incompatible sources."""
        sources = [self.shared_tests.prepare_source(SourceType.LIVE_OS_IMAGE)]

        cm = self.shared_tests.set_and_check_sources(
            sources, exception=IncompatibleSourceError)

        msg = "Source type {} is not supported by this payload.".format(
            SourceType.LIVE_OS_IMAGE.value)
        self.assertEqual(str(cm.exception), msg)

    @patch.object(DNFModule, "supported_source_types",
                  [SourceType.NFS, SourceType.URL])
    @patch_dbus_publish_object
    def set_when_initialized_source_fail_test(self, publisher):
        """Test payload can't set new sources if the old ones are initialized."""
        source1 = self.shared_tests.prepare_source(SourceType.NFS)
        source2 = self.shared_tests.prepare_source(
            SourceType.URL, state=SourceState.NOT_APPLICABLE)

        self.shared_tests.set_and_check_sources([source1])

        # can't switch source if attached source is ready
        source1.get_state.return_value = SourceState.READY
        self.shared_tests.set_sources([source2], SourceSetupError)
        self.shared_tests.check_sources([source1])

        # change to source2 when attached source state is UNREADY
        source1.get_state.return_value = SourceState.UNREADY
        self.shared_tests.set_and_check_sources([source2])

        # can change back anytime because source2 has state NOT_APPLICABLE
        self.shared_tests.set_and_check_sources([source1])
class PayloadBaseInterfaceTestCase(unittest.TestCase):

    def setUp(self):
        self.module = DNFModule()
        self.interface = DNFInterface(self.module)

        self.shared_tests = PayloadSharedTest(self,
                                              payload=self.module,
                                              payload_intf=self.interface)

    def type_test(self):
        self.shared_tests.check_type(PayloadType.DNF)

    @patch.object(DNFModule, "supported_source_types", [SourceType.URL])
    def supported_sources_test(self):
        """Test supported sources API."""
        self.assertEqual(
            [SourceType.URL.value],
            self.interface.SupportedSourceTypes)

    def sources_empty_test(self):
        """Test sources API for emptiness."""
        self.shared_tests.check_empty_sources()

    @patch.object(DNFModule, "supported_source_types", [SourceType.URL])
    @patch_dbus_publish_object
    def set_source_test(self, publisher):
        """Test if set source API payload."""
        sources = [self.shared_tests.prepare_source(SourceType.URL)]

        self.shared_tests.set_and_check_sources(sources)

    @patch.object(DNFModule, "supported_source_types", [SourceType.URL])
    @patch_dbus_publish_object
    def add_source_test(self, publisher):
        """Test module API to add source."""
        source1 = self.shared_tests.prepare_source(SourceType.URL, SourceState.NOT_APPLICABLE)

        sources = [source1]
        self.shared_tests.set_and_check_sources(sources)

        source2 = self.shared_tests.prepare_source(SourceType.URL)
        self.module.add_source(source2)

        sources.append(source2)
        self.shared_tests.check_sources(sources)

    @patch.object(DNFModule, "supported_source_types", [SourceType.URL])
    @patch_dbus_publish_object
    def add_source_incompatible_source_failed_test(self, publisher):
        """Test module API to add source failed with incompatible source."""
        source1 = self.shared_tests.prepare_source(SourceType.URL, SourceState.NOT_APPLICABLE)

        sources = [source1]
        self.shared_tests.set_and_check_sources(sources)

        source2 = self.shared_tests.prepare_source(SourceType.NFS)
        with self.assertRaises(IncompatibleSourceError):
            self.module.add_source(source2)

        self.shared_tests.check_sources(sources)

    @patch.object(DNFModule, "supported_source_types", [SourceType.URL])
    @patch_dbus_publish_object
    def add_source_ready_failed_test(self, publisher):
        """Test module API to add source failed with ready source."""
        source1 = self.shared_tests.prepare_source(SourceType.URL, SourceState.READY)

        sources = [source1]
        self.shared_tests.set_and_check_sources(sources)

        source2 = self.shared_tests.prepare_source(SourceType.URL)
        with self.assertRaises(SourceSetupError):
            self.module.add_source(source2)

        self.shared_tests.check_sources(sources)

    @patch.object(DNFModule, "supported_source_types", [SourceType.URL, SourceType.NFS])
    @patch_dbus_publish_object
    def set_multiple_source_test(self, publisher):
        """Test payload setting multiple compatible sources."""
        sources = [
            self.shared_tests.prepare_source(SourceType.NFS),
            self.shared_tests.prepare_source(SourceType.URL),
            self.shared_tests.prepare_source(SourceType.URL),
        ]

        self.shared_tests.set_and_check_sources(sources)

    @patch.object(DNFModule, "supported_source_types", [SourceType.URL])
    @patch_dbus_publish_object
    def set_incompatible_source_test(self, publisher):
        """Test payload setting incompatible sources."""
        sources = [self.shared_tests.prepare_source(SourceType.LIVE_OS_IMAGE)]

        cm = self.shared_tests.set_and_check_sources(sources, exception=IncompatibleSourceError)

        msg = "Source type {} is not supported by this payload.".format(
            SourceType.LIVE_OS_IMAGE.value)
        self.assertEqual(str(cm.exception), msg)

    @patch.object(DNFModule, "supported_source_types", [SourceType.NFS, SourceType.URL])
    @patch_dbus_publish_object
    def set_when_initialized_source_fail_test(self, publisher):
        """Test payload can't set new sources if the old ones are initialized."""
        source1 = self.shared_tests.prepare_source(SourceType.NFS)
        source2 = self.shared_tests.prepare_source(SourceType.URL, state=SourceState.NOT_APPLICABLE)

        self.shared_tests.set_and_check_sources([source1])

        # can't switch source if attached source is ready
        source1.get_state.return_value = SourceState.READY
        self.shared_tests.set_sources([source2], SourceSetupError)
        self.shared_tests.check_sources([source1])

        # change to source2 when attached source state is UNREADY
        source1.get_state.return_value = SourceState.UNREADY
        self.shared_tests.set_and_check_sources([source2])

        # can change back anytime because source2 has state NOT_APPLICABLE
        self.shared_tests.set_and_check_sources([source1])

    @patch_dbus_publish_object
    def is_network_required_test(self, publisher):
        """Test IsNetworkRequired."""
        self.assertEqual(self.interface.IsNetworkRequired(), False)

        source1 = self.shared_tests.prepare_source(SourceType.CDROM, state=SourceState.UNREADY)
        self.shared_tests.set_sources([source1])

        self.assertEqual(self.interface.IsNetworkRequired(), False)

        source2 = self.shared_tests.prepare_source(SourceType.NFS, state=SourceState.UNREADY)
        self.shared_tests.set_sources([source1, source2])

        self.assertEqual(self.interface.IsNetworkRequired(), True)

    @patch_dbus_publish_object
    def calculate_required_space_test(self, publisher):
        """Test CalculateRequiredTest."""
        self.assertEqual(self.interface.CalculateRequiredSpace(), 0)

        source1 = self.shared_tests.prepare_source(SourceType.CDROM, state=SourceState.UNREADY)
        self.shared_tests.set_sources([source1])

        self.assertEqual(self.interface.CalculateRequiredSpace(), 0)

    @patch_dbus_publish_object
    def set_up_sources_with_task_test(self, publisher):
        """Test SetUpSourcesWithTask."""
        source = SourceFactory.create_source(SourceType.CDROM)
        self.module.add_source(source)

        task_path = self.interface.SetUpSourcesWithTask()
        obj = check_task_creation(self, task_path, publisher, SetUpSourcesTask)
        self.assertEqual(obj.implementation._sources, [source])

    @patch_dbus_publish_object
    def tear_down_sources_with_task_test(self, publisher):
        """Test TearDownSourcesWithTask."""
        source = SourceFactory.create_source(SourceType.CDROM)
        self.module.add_source(source)

        task_path = self.interface.TearDownSourcesWithTask()
        obj = check_task_creation(self, task_path, publisher, TearDownSourcesTask)
        self.assertEqual(obj.implementation._sources, [source])