class ServiceWaiterFunctionalTest(BaseEnvVar):
    """
    This class is used as a base class if you want to functionally test the
    waiters for a specific service.
    """
    def setUp(self):
        super(ServiceWaiterFunctionalTest, self).setUp()
        self.data_path = os.path.join(
            os.path.dirname(ibm_botocore.__file__), 'data')
        self.environ['AWS_DATA_PATH'] = self.data_path
        self.loader = Loader([self.data_path])

    def get_waiter_model(self, service, api_version=None):
        """Get the waiter model for the service."""
        with mock.patch('ibm_botocore.loaders.Loader.list_available_services',
                        return_value=[service]):
            return WaiterModel(self.loader.load_service_model(
                service, type_name='waiters-2', api_version=api_version))

    def get_service_model(self, service, api_version=None):
        """Get the service model for the service."""
        with mock.patch('ibm_botocore.loaders.Loader.list_available_services',
                        return_value=[service]):
            return ServiceModel(
                self.loader.load_service_model(
                    service, type_name='service-2', api_version=api_version),
                service_name=service
            )
    def test_load_service_model_uses_provided_type_name(self):
        loader = Loader(extra_search_paths=['foo'],
                        file_loader=mock.Mock(),
                        include_default_search_paths=False)
        loader.list_available_services = mock.Mock(return_value=['baz'])

        # Should have a) the unknown service name and b) list of valid
        # service names.
        provided_type_name = 'not-service-2'
        with self.assertRaisesRegexp(UnknownServiceError,
                                     'Unknown service.*BAZ.*baz'):
            loader.load_service_model('BAZ', type_name=provided_type_name)

        loader.list_available_services.assert_called_with(provided_type_name)
def test_paginators_and_waiters_are_not_lost_in_new_version(
        service_name, type_name, previous_version, latest_version):
    # Make sure if a paginator and/or waiter exists in previous version,
    # there will be a successor existing in latest version.
    loader = Loader()
    try:
        loader.load_service_model(service_name, type_name, previous_version)
    except DataNotFoundError:
        pass
    else:
        try:
            loader.load_service_model(service_name, type_name, latest_version)
        except DataNotFoundError as e:
            raise AssertionError(
                f"{type_name} must exist for {service_name}: {e}")
    def test_load_service_model_enforces_case(self):
        class FakeLoader(object):
            def load_file(self, name):
                return ['loaded data']

        loader = Loader(extra_search_paths=['foo'],
                        file_loader=FakeLoader(),
                        include_default_search_paths=False)
        loader.determine_latest_version = mock.Mock(return_value='2015-03-01')
        loader.list_available_services = mock.Mock(return_value=['baz'])

        # Should have a) the unknown service name and b) list of valid
        # service names.
        with self.assertRaisesRegexp(UnknownServiceError,
                                     'Unknown service.*BAZ.*baz'):
            loader.load_service_model('BAZ', type_name='service-2')
def _test_model_is_not_lost(service_name, type_name, previous_version,
                            latest_version):
    # Make sure if a paginator and/or waiter exists in previous version,
    # there will be a successor existing in latest version.
    loader = Loader()
    try:
        previous = loader.load_service_model(service_name, type_name,
                                             previous_version)
    except DataNotFoundError:
        pass
    else:
        try:
            latest = loader.load_service_model(service_name, type_name,
                                               latest_version)
        except DataNotFoundError as e:
            raise AssertionError("%s must exist for %s: %s" %
                                 (type_name, service_name, e))
    def test_load_service_model(self):
        class FakeLoader(object):
            def load_file(self, name):
                return ['loaded data']

        loader = Loader(extra_search_paths=['foo'],
                        file_loader=FakeLoader(),
                        include_default_search_paths=False,
                        include_default_extras=False)
        loader.determine_latest_version = mock.Mock(return_value='2015-03-01')
        loader.list_available_services = mock.Mock(return_value=['baz'])
        loaded = loader.load_service_model('baz', type_name='service-2')
        self.assertEqual(loaded, ['loaded data'])
class TestMergeExtras(BaseEnvVar):
    def setUp(self):
        super(TestMergeExtras, self).setUp()
        self.file_loader = mock.Mock()
        self.data_loader = Loader(extra_search_paths=['datapath'],
                                  file_loader=self.file_loader,
                                  include_default_search_paths=False)
        self.data_loader.determine_latest_version = mock.Mock(
            return_value='2015-03-01')
        self.data_loader.list_available_services = mock.Mock(
            return_value=['myservice'])

        isdir_mock = mock.Mock(return_value=True)
        self.isdir_patch = mock.patch('os.path.isdir', isdir_mock)
        self.isdir_patch.start()

    def tearDown(self):
        super(TestMergeExtras, self).tearDown()
        self.isdir_patch.stop()

    def test_merge_extras(self):
        service_data = {'foo': 'service', 'bar': 'service'}
        sdk_extras = {'merge': {'foo': 'sdk'}}
        self.file_loader.load_file.side_effect = [service_data, sdk_extras]

        loaded = self.data_loader.load_service_model('myservice', 'service-2')
        expected = {'foo': 'sdk', 'bar': 'service'}
        self.assertEqual(loaded, expected)

        call_args = self.file_loader.load_file.call_args_list
        call_args = [c[0][0] for c in call_args]
        base_path = os.path.join('datapath', 'myservice', '2015-03-01')
        expected_call_args = [
            os.path.join(base_path, 'service-2'),
            os.path.join(base_path, 'service-2.sdk-extras')
        ]
        self.assertEqual(call_args, expected_call_args)

    def test_extras_not_found(self):
        service_data = {'foo': 'service', 'bar': 'service'}
        service_data_copy = copy.copy(service_data)
        self.file_loader.load_file.side_effect = [service_data, None]

        loaded = self.data_loader.load_service_model('myservice', 'service-2')
        self.assertEqual(loaded, service_data_copy)

    def test_no_merge_in_extras(self):
        service_data = {'foo': 'service', 'bar': 'service'}
        service_data_copy = copy.copy(service_data)
        self.file_loader.load_file.side_effect = [service_data, {}]

        loaded = self.data_loader.load_service_model('myservice', 'service-2')
        self.assertEqual(loaded, service_data_copy)

    def test_include_default_extras(self):
        self.data_loader = Loader(extra_search_paths=['datapath'],
                                  file_loader=self.file_loader,
                                  include_default_search_paths=False,
                                  include_default_extras=False)
        self.data_loader.determine_latest_version = mock.Mock(
            return_value='2015-03-01')
        self.data_loader.list_available_services = mock.Mock(
            return_value=['myservice'])

        service_data = {'foo': 'service', 'bar': 'service'}
        service_data_copy = copy.copy(service_data)
        sdk_extras = {'merge': {'foo': 'sdk'}}
        self.file_loader.load_file.side_effect = [service_data, sdk_extras]

        loaded = self.data_loader.load_service_model('myservice', 'service-2')
        self.assertEqual(loaded, service_data_copy)

    def test_append_extra_type(self):
        service_data = {'foo': 'service', 'bar': 'service'}
        sdk_extras = {'merge': {'foo': 'sdk'}}
        cli_extras = {'merge': {'cli': True}}
        self.file_loader.load_file.side_effect = [
            service_data, sdk_extras, cli_extras
        ]

        self.data_loader.extras_types.append('cli')

        loaded = self.data_loader.load_service_model('myservice', 'service-2')
        expected = {'foo': 'sdk', 'bar': 'service', 'cli': True}
        self.assertEqual(loaded, expected)

        call_args = self.file_loader.load_file.call_args_list
        call_args = [c[0][0] for c in call_args]
        base_path = os.path.join('datapath', 'myservice', '2015-03-01')
        expected_call_args = [
            os.path.join(base_path, 'service-2'),
            os.path.join(base_path, 'service-2.sdk-extras'),
            os.path.join(base_path, 'service-2.cli-extras')
        ]
        self.assertEqual(call_args, expected_call_args)

    def test_sdk_empty_extras_skipped(self):
        service_data = {'foo': 'service', 'bar': 'service'}
        cli_extras = {'merge': {'foo': 'cli'}}
        self.file_loader.load_file.side_effect = [
            service_data, None, cli_extras
        ]

        self.data_loader.extras_types.append('cli')

        loaded = self.data_loader.load_service_model('myservice', 'service-2')
        expected = {'foo': 'cli', 'bar': 'service'}
        self.assertEqual(loaded, expected)