"Fossies" - the Fresh Open Source Software Archive

Member "octavia-8.0.0/octavia/tests/unit/common/test_validate.py" (14 Apr 2021, 23468 Bytes) of package /linux/misc/openstack/octavia-8.0.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file.

    1 # Copyright 2016 Blue Box, an IBM Company
    2 #
    3 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
    4 #    not use this file except in compliance with the License. You may obtain
    5 #    a copy of the License at
    6 #
    7 #         http://www.apache.org/licenses/LICENSE-2.0
    8 #
    9 #    Unless required by applicable law or agreed to in writing, software
   10 #    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
   11 #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
   12 #    License for the specific language governing permissions and limitations
   13 #    under the License.
   14 from unittest import mock
   15 
   16 from oslo_config import cfg
   17 from oslo_config import fixture as oslo_fixture
   18 from oslo_utils import uuidutils
   19 
   20 import octavia.common.constants as constants
   21 import octavia.common.exceptions as exceptions
   22 import octavia.common.validate as validate
   23 from octavia.network import base as network_base
   24 from octavia.network import data_models as network_models
   25 import octavia.tests.unit.base as base
   26 
   27 
   28 class TestValidations(base.TestCase):
   29     # Note that particularly complex validation testing is handled via
   30     # functional tests elsewhere (ex. repository tests)
   31 
   32     def setUp(self):
   33         super().setUp()
   34         self.conf = oslo_fixture.Config(cfg.CONF)
   35 
   36     def test_validate_url(self):
   37         ret = validate.url('http://example.com')
   38         self.assertTrue(ret)
   39 
   40     def test_validate_bad_url(self):
   41         self.assertRaises(exceptions.InvalidURL, validate.url, 'bad url')
   42 
   43     def test_validate_url_bad_schema(self):
   44         self.assertRaises(exceptions.InvalidURL, validate.url,
   45                           'ssh://www.example.com/')
   46 
   47     def test_validate_header_name(self):
   48         ret = validate.header_name('Some-header')
   49         self.assertTrue(ret)
   50 
   51     def test_validate_bad_header_name(self):
   52         self.assertRaises(exceptions.InvalidString,
   53                           validate.cookie_value_string,
   54                           'bad header')
   55 
   56     def test_validate_cookie_value_string(self):
   57         ret = validate.cookie_value_string('some-cookie')
   58         self.assertTrue(ret)
   59 
   60     def test_validate_bad_cookie_value_string(self):
   61         self.assertRaises(exceptions.InvalidString,
   62                           validate.cookie_value_string,
   63                           'bad cookie value;')
   64 
   65     def test_validate_header_value_string(self):
   66         ret = validate.header_value_string('some-value')
   67         self.assertTrue(ret)
   68 
   69     def test_validate_header_value_string_quoted(self):
   70         ret = validate.header_value_string('"some value"')
   71         self.assertTrue(ret)
   72 
   73     def test_validate_bad_header_value_string(self):
   74         self.assertRaises(exceptions.InvalidString,
   75                           validate.header_value_string,
   76                           '\x18')
   77 
   78     def test_validate_regex(self):
   79         ret = validate.regex('some regex.*')
   80         self.assertTrue(ret)
   81 
   82     def test_validate_bad_regex(self):
   83         self.assertRaises(exceptions.InvalidRegex, validate.regex,
   84                           'bad regex\\')
   85 
   86     def test_sanitize_l7policy_api_args_action_reject(self):
   87         l7p = {'action': constants.L7POLICY_ACTION_REJECT,
   88                'redirect_url': 'http://www.example.com/',
   89                'redirect_pool_id': 'test-pool',
   90                'redirect_pool': {
   91                    'protocol': constants.PROTOCOL_HTTP,
   92                    'lb_algorithm': constants.LB_ALGORITHM_ROUND_ROBIN}}
   93         s_l7p = validate.sanitize_l7policy_api_args(l7p)
   94         self.assertIsNone(s_l7p['redirect_url'])
   95         self.assertIsNone(s_l7p['redirect_pool_id'])
   96         self.assertNotIn('redirect_pool', s_l7p.keys())
   97 
   98     def test_sanitize_l7policy_api_args_action_rdr_pool_id(self):
   99         l7p = {'action': constants.L7POLICY_ACTION_REDIRECT_TO_POOL,
  100                'redirect_url': 'http://www.example.com/',
  101                'redirect_pool_id': 'test-pool',
  102                'redirect_pool': {
  103                    'protocol': constants.PROTOCOL_HTTP,
  104                    'lb_algorithm': constants.LB_ALGORITHM_ROUND_ROBIN}}
  105         s_l7p = validate.sanitize_l7policy_api_args(l7p)
  106         self.assertIsNone(s_l7p['redirect_url'])
  107         self.assertNotIn('redirect_pool', s_l7p.keys())
  108         self.assertIn('redirect_pool_id', s_l7p.keys())
  109 
  110     def test_sanitize_l7policy_api_args_action_rdr_pool_model(self):
  111         l7p = {'action': constants.L7POLICY_ACTION_REDIRECT_TO_POOL,
  112                'redirect_url': 'http://www.example.com/',
  113                'redirect_pool_id': None,
  114                'redirect_pool': {
  115                    'protocol': constants.PROTOCOL_HTTP,
  116                    'lb_algorithm': constants.LB_ALGORITHM_ROUND_ROBIN}}
  117         s_l7p = validate.sanitize_l7policy_api_args(l7p)
  118         self.assertIsNone(s_l7p['redirect_url'])
  119         self.assertNotIn('redirect_pool_id', s_l7p.keys())
  120         self.assertIn('redirect_pool', s_l7p.keys())
  121 
  122     def test_sanitize_l7policy_api_args_action_rdr_url(self):
  123         l7p = {'action': constants.L7POLICY_ACTION_REDIRECT_TO_URL,
  124                'redirect_url': 'http://www.example.com/',
  125                'redirect_pool_id': 'test-pool',
  126                'redirect_pool': {
  127                    'protocol': constants.PROTOCOL_HTTP,
  128                    'lb_algorithm': constants.LB_ALGORITHM_ROUND_ROBIN}}
  129         s_l7p = validate.sanitize_l7policy_api_args(l7p)
  130         self.assertIn('redirect_url', s_l7p.keys())
  131         self.assertIsNone(s_l7p['redirect_pool_id'])
  132         self.assertNotIn('redirect_pool', s_l7p.keys())
  133 
  134     def test_sanitize_l7policy_api_args_bad_action(self):
  135         l7p = {'action': 'bad-action',
  136                'redirect_url': 'http://www.example.com/',
  137                'redirect_pool_id': 'test-pool',
  138                'redirect_pool': {
  139                    'protocol': constants.PROTOCOL_HTTP,
  140                    'lb_algorithm': constants.LB_ALGORITHM_ROUND_ROBIN}}
  141         self.assertRaises(exceptions.InvalidL7PolicyAction,
  142                           validate.sanitize_l7policy_api_args, l7p)
  143 
  144     def test_sanitize_l7policy_api_args_action_none(self):
  145         l7p = {'action': None}
  146         self.assertRaises(exceptions.InvalidL7PolicyAction,
  147                           validate.sanitize_l7policy_api_args, l7p, True)
  148 
  149     def test_sanitize_l7policy_api_args_both_rdr_args_a(self):
  150         l7p = {'redirect_url': 'http://www.example.com/',
  151                'redirect_pool_id': 'test-pool'}
  152         self.assertRaises(exceptions.InvalidL7PolicyArgs,
  153                           validate.sanitize_l7policy_api_args, l7p)
  154 
  155     def test_sanitize_l7policy_api_args_both_rdr_args_b(self):
  156         l7p = {'redirect_url': 'http://www.example.com/',
  157                'redirect_pool': {
  158                    'protocol': constants.PROTOCOL_HTTP,
  159                    'lb_algorithm': constants.LB_ALGORITHM_ROUND_ROBIN}}
  160         self.assertRaises(exceptions.InvalidL7PolicyArgs,
  161                           validate.sanitize_l7policy_api_args, l7p)
  162 
  163     def test_sanitize_l7policy_api_args_rdr_pool_id(self):
  164         l7p = {'redirect_pool_id': 'test-pool',
  165                'redirect_url': None,
  166                'redirect_pool': None}
  167         s_l7p = validate.sanitize_l7policy_api_args(l7p)
  168         self.assertIn('redirect_pool_id', s_l7p.keys())
  169         self.assertIsNone(s_l7p['redirect_url'])
  170         self.assertNotIn('redirect_pool', s_l7p.keys())
  171         self.assertIn('action', s_l7p.keys())
  172         self.assertEqual(constants.L7POLICY_ACTION_REDIRECT_TO_POOL,
  173                          s_l7p['action'])
  174 
  175     def test_sanitize_l7policy_api_args_rdr_pool_noid(self):
  176         l7p = {'redirect_pool_id': None,
  177                'redirect_url': None,
  178                'redirect_pool': {
  179                    'protocol': constants.PROTOCOL_HTTP,
  180                    'lb_algorithm': constants.LB_ALGORITHM_ROUND_ROBIN}}
  181         s_l7p = validate.sanitize_l7policy_api_args(l7p)
  182         self.assertIn('redirect_pool', s_l7p.keys())
  183         self.assertIsNone(s_l7p['redirect_url'])
  184         self.assertNotIn('redirect_pool_id', s_l7p.keys())
  185         self.assertIn('action', s_l7p.keys())
  186         self.assertEqual(constants.L7POLICY_ACTION_REDIRECT_TO_POOL,
  187                          s_l7p['action'])
  188 
  189     def test_sanitize_l7policy_api_args_rdr_pool_id_none_create(self):
  190         l7p = {'redirect_pool_id': None}
  191         self.assertRaises(exceptions.InvalidL7PolicyAction,
  192                           validate.sanitize_l7policy_api_args, l7p, True)
  193 
  194     def test_sanitize_l7policy_api_args_rdr_pool_noid_none_create(self):
  195         l7p = {'redirect_pool': None}
  196         self.assertRaises(exceptions.InvalidL7PolicyAction,
  197                           validate.sanitize_l7policy_api_args, l7p, True)
  198 
  199     def test_sanitize_l7policy_api_args_rdr_pool_both_none_create(self):
  200         l7p = {'redirect_pool': None,
  201                'redirect_pool_id': None}
  202         self.assertRaises(exceptions.InvalidL7PolicyAction,
  203                           validate.sanitize_l7policy_api_args, l7p, True)
  204 
  205     def test_sanitize_l7policy_api_args_rdr_url(self):
  206         l7p = {'redirect_pool_id': None,
  207                'redirect_url': 'http://www.example.com/',
  208                'redirect_pool': None}
  209         s_l7p = validate.sanitize_l7policy_api_args(l7p)
  210         self.assertIsNone(s_l7p['redirect_pool_id'])
  211         self.assertNotIn('redirect_pool', s_l7p.keys())
  212         self.assertIn('redirect_url', s_l7p.keys())
  213         self.assertIn('action', s_l7p.keys())
  214         self.assertEqual(constants.L7POLICY_ACTION_REDIRECT_TO_URL,
  215                          s_l7p['action'])
  216 
  217     def test_sanitize_l7policy_api_args_rdr_url_none_create(self):
  218         l7p = {'redirect_url': None}
  219         self.assertRaises(exceptions.InvalidL7PolicyAction,
  220                           validate.sanitize_l7policy_api_args, l7p, True)
  221 
  222     def test_sanitize_l7policy_api_args_rdr_url_bad_url(self):
  223         l7p = {'redirect_url': 'bad url'}
  224         self.assertRaises(exceptions.InvalidURL,
  225                           validate.sanitize_l7policy_api_args, l7p, True)
  226 
  227     def test_sanitize_l7policy_api_args_update_action_rdr_pool_arg(self):
  228         l7p = {'action': constants.L7POLICY_ACTION_REDIRECT_TO_POOL,
  229                'redirect_url': None,
  230                'redirect_pool_id': None,
  231                'redirect_pool': None}
  232         self.assertRaises(exceptions.InvalidL7PolicyArgs,
  233                           validate.sanitize_l7policy_api_args, l7p)
  234 
  235     def test_sanitize_l7policy_api_args_update_action_rdr_url_arg(self):
  236         l7p = {'action': constants.L7POLICY_ACTION_REDIRECT_TO_URL,
  237                'redirect_url': None,
  238                'redirect_pool_id': None,
  239                'redirect_pool': None}
  240         self.assertRaises(exceptions.InvalidL7PolicyArgs,
  241                           validate.sanitize_l7policy_api_args, l7p)
  242 
  243     def test_sanitize_l7policy_api_args_create_must_have_action(self):
  244         l7p = {}
  245         self.assertRaises(exceptions.InvalidL7PolicyAction,
  246                           validate.sanitize_l7policy_api_args, l7p, True)
  247 
  248     def test_sanitize_l7policy_api_args_update_must_have_args(self):
  249         l7p = {}
  250         self.assertRaises(exceptions.InvalidL7PolicyArgs,
  251                           validate.sanitize_l7policy_api_args, l7p)
  252 
  253     def test_port_exists_with_bad_port(self):
  254         port_id = uuidutils.generate_uuid()
  255         with mock.patch(
  256                 'octavia.common.utils.get_network_driver') as net_mock:
  257             net_mock.return_value.get_port = mock.Mock(
  258                 side_effect=network_base.PortNotFound('Port not found'))
  259             self.assertRaises(
  260                 exceptions.InvalidSubresource,
  261                 validate.port_exists, port_id)
  262 
  263     def test_port_exists_with_valid_port(self):
  264         port_id = uuidutils.generate_uuid()
  265         port = network_models.Port(id=port_id)
  266         with mock.patch(
  267                 'octavia.common.utils.get_network_driver') as net_mock:
  268             net_mock.return_value.get_port.return_value = port
  269             self.assertEqual(validate.port_exists(port_id), port)
  270 
  271     def test_check_port_in_use(self):
  272         port_id = uuidutils.generate_uuid()
  273         device_id = uuidutils.generate_uuid()
  274         port = network_models.Port(id=port_id, device_id=device_id)
  275         with mock.patch(
  276                 'octavia.common.utils.get_network_driver') as net_mock:
  277             net_mock.return_value.get_port.device_id = port
  278             self.assertRaises(
  279                 exceptions.ValidationException,
  280                 validate.check_port_in_use, port)
  281 
  282     def test_subnet_exists_with_bad_subnet(self):
  283         subnet_id = uuidutils.generate_uuid()
  284         with mock.patch(
  285                 'octavia.common.utils.get_network_driver') as net_mock:
  286             net_mock.return_value.get_subnet = mock.Mock(
  287                 side_effect=network_base.SubnetNotFound('Subnet not found'))
  288             self.assertRaises(
  289                 exceptions.InvalidSubresource,
  290                 validate.subnet_exists, subnet_id)
  291 
  292     def test_subnet_exists_with_valid_subnet(self):
  293         subnet_id = uuidutils.generate_uuid()
  294         subnet = network_models.Subnet(id=subnet_id)
  295         with mock.patch(
  296                 'octavia.common.utils.get_network_driver') as net_mock:
  297             net_mock.return_value.get_subnet.return_value = subnet
  298             self.assertEqual(validate.subnet_exists(subnet_id), subnet)
  299 
  300     def test_network_exists_with_bad_network(self):
  301         network_id = uuidutils.generate_uuid()
  302         with mock.patch(
  303                 'octavia.common.utils.get_network_driver') as net_mock:
  304             net_mock.return_value.get_network = mock.Mock(
  305                 side_effect=network_base.NetworkNotFound('Network not found'))
  306             self.assertRaises(
  307                 exceptions.InvalidSubresource,
  308                 validate.network_exists_optionally_contains_subnet, network_id)
  309 
  310     def test_network_exists_with_valid_network(self):
  311         network_id = uuidutils.generate_uuid()
  312         network = network_models.Network(id=network_id)
  313         with mock.patch(
  314                 'octavia.common.utils.get_network_driver') as net_mock:
  315             net_mock.return_value.get_network.return_value = network
  316             self.assertEqual(
  317                 validate.network_exists_optionally_contains_subnet(network_id),
  318                 network)
  319 
  320     def test_network_exists_with_valid_subnet(self):
  321         network_id = uuidutils.generate_uuid()
  322         subnet_id = uuidutils.generate_uuid()
  323         network = network_models.Network(
  324             id=network_id,
  325             subnets=[subnet_id])
  326         with mock.patch(
  327                 'octavia.common.utils.get_network_driver') as net_mock:
  328             net_mock.return_value.get_network.return_value = network
  329             self.assertEqual(
  330                 validate.network_exists_optionally_contains_subnet(
  331                     network_id, subnet_id),
  332                 network)
  333 
  334     def test_network_exists_with_bad_subnet(self):
  335         network_id = uuidutils.generate_uuid()
  336         subnet_id = uuidutils.generate_uuid()
  337         network = network_models.Network(id=network_id)
  338         with mock.patch(
  339                 'octavia.common.utils.get_network_driver') as net_mock:
  340             net_mock.return_value.get_network.return_value = network
  341             self.assertRaises(
  342                 exceptions.InvalidSubresource,
  343                 validate.network_exists_optionally_contains_subnet,
  344                 network_id, subnet_id)
  345 
  346     def test_network_allowed_by_config(self):
  347         net_id1 = uuidutils.generate_uuid()
  348         net_id2 = uuidutils.generate_uuid()
  349         net_id3 = uuidutils.generate_uuid()
  350         valid_net_ids = ",".join((net_id1, net_id2))
  351         self.conf.config(group="networking", valid_vip_networks=valid_net_ids)
  352         validate.network_allowed_by_config(net_id1)
  353         validate.network_allowed_by_config(net_id2)
  354         self.assertRaises(
  355             exceptions.ValidationException,
  356             validate.network_allowed_by_config, net_id3)
  357 
  358     def test_qos_policy_exists(self):
  359         qos_policy_id = uuidutils.generate_uuid()
  360         qos_policy = network_models.QosPolicy(id=qos_policy_id)
  361         with mock.patch(
  362                 'octavia.common.utils.get_network_driver') as net_mock:
  363             net_mock.return_value.get_qos_policy.return_value = qos_policy
  364             self.assertEqual(
  365                 validate.qos_policy_exists(qos_policy_id),
  366                 qos_policy)
  367 
  368             net_mock.return_value.get_qos_policy.side_effect = Exception
  369             self.assertRaises(exceptions.InvalidSubresource,
  370                               validate.qos_policy_exists,
  371                               qos_policy_id)
  372 
  373     def test_qos_extension_enabled(self):
  374         network_driver = mock.Mock()
  375         network_driver.qos_enabled.return_value = True
  376         self.assertIsNone(validate.qos_extension_enabled(network_driver))
  377 
  378     def test_qos_extension_disabled(self):
  379         network_driver = mock.Mock()
  380         network_driver.qos_enabled.return_value = False
  381         self.assertRaises(exceptions.ValidationException,
  382                           validate.qos_extension_enabled,
  383                           network_driver)
  384 
  385     def test_check_session_persistence(self):
  386         valid_cookie_name_dict = {'type': 'APP_COOKIE',
  387                                   'cookie_name': 'chocolate_chip'}
  388         invalid_cookie_name_dict = {'type': 'APP_COOKIE',
  389                                     'cookie_name': '@chocolate_chip'}
  390         invalid_type_HTTP_cookie_name_dict = {'type': 'HTTP_COOKIE',
  391                                               'cookie_name': 'chocolate_chip'}
  392         invalid_type_IP_cookie_name_dict = {'type': 'SOURCE_IP',
  393                                             'cookie_name': 'chocolate_chip'}
  394         invalid_missing_cookie_name_dict = {'type': 'APP_COOKIE'}
  395 
  396         # Validate that a good cookie name passes
  397         validate.check_session_persistence(valid_cookie_name_dict)
  398 
  399         # Test raises with providing an invalid cookie name
  400         self.assertRaises(exceptions.ValidationException,
  401                           validate.check_session_persistence,
  402                           invalid_cookie_name_dict)
  403 
  404         # Test raises type HTTP_COOKIE and providing cookie_name
  405         self.assertRaises(exceptions.ValidationException,
  406                           validate.check_session_persistence,
  407                           invalid_type_HTTP_cookie_name_dict)
  408 
  409         # Test raises type SOURCE_IP and providing cookie_name
  410         self.assertRaises(exceptions.ValidationException,
  411                           validate.check_session_persistence,
  412                           invalid_type_IP_cookie_name_dict)
  413 
  414         # Test raises when type APP_COOKIE but no cookie_name
  415         self.assertRaises(exceptions.ValidationException,
  416                           validate.check_session_persistence,
  417                           invalid_missing_cookie_name_dict)
  418 
  419         # Test catch all exception raises a user friendly message
  420         with mock.patch('re.compile') as compile_mock:
  421             compile_mock.side_effect = Exception
  422             self.assertRaises(exceptions.ValidationException,
  423                               validate.check_session_persistence,
  424                               valid_cookie_name_dict)
  425 
  426     def test_ip_not_reserved(self):
  427         self.conf.config(group="networking", reserved_ips=['198.51.100.4'])
  428 
  429         # Test good address
  430         validate.ip_not_reserved('203.0.113.5')
  431 
  432         # Test IPv4 reserved address
  433         self.assertRaises(exceptions.InvalidOption,
  434                           validate.ip_not_reserved,
  435                           '198.51.100.4')
  436 
  437         self.conf.config(
  438             group="networking",
  439             reserved_ips=['2001:0DB8:0000:0000:0000:0000:0000:0005'])
  440 
  441         # Test good IPv6 address
  442         validate.ip_not_reserved('2001:0DB8::9')
  443 
  444         # Test reserved IPv6 expanded
  445         self.assertRaises(exceptions.InvalidOption,
  446                           validate.ip_not_reserved,
  447                           '2001:0DB8:0000:0000:0000:0000:0000:0005')
  448 
  449         # Test reserved IPv6 short hand notation
  450         self.assertRaises(exceptions.InvalidOption,
  451                           validate.ip_not_reserved,
  452                           '2001:0DB8::5')
  453 
  454     def test_is_flavor_spares_compatible(self):
  455         not_compat_flavor = {constants.COMPUTE_FLAVOR: 'chocolate'}
  456         compat_flavor = {constants.LOADBALANCER_TOPOLOGY:
  457                          constants.TOPOLOGY_SINGLE}
  458 
  459         self.assertTrue(validate.is_flavor_spares_compatible(None))
  460         self.assertTrue(validate.is_flavor_spares_compatible(compat_flavor))
  461         self.assertFalse(
  462             validate.is_flavor_spares_compatible(not_compat_flavor))
  463 
  464     def test_check_default_ciphers_prohibit_list_conflict(self):
  465         self.conf.config(group='api_settings',
  466                          tls_cipher_prohibit_list='PSK-AES128-CBC-SHA')
  467         self.conf.config(group='api_settings',
  468                          default_listener_ciphers='ECDHE-ECDSA-AES256-SHA:'
  469                          'PSK-AES128-CBC-SHA:TLS_AES_256_GCM_SHA384')
  470 
  471         self.assertRaises(
  472             exceptions.ValidationException,
  473             validate.check_default_ciphers_prohibit_list_conflict)
  474 
  475     def test_check_tls_version_list(self):
  476         # Test valid list
  477         validate.check_tls_version_list(['TLSv1.1', 'TLSv1.2', 'TLSv1.3'])
  478         # Test invalid list
  479         self.assertRaises(
  480             exceptions.ValidationException,
  481             validate.check_tls_version_list,
  482             ['SSLv3', 'TLSv1.0'])
  483         # Test empty list
  484         self.assertRaises(
  485             exceptions.ValidationException,
  486             validate.check_tls_version_list,
  487             [])
  488 
  489     def test_check_tls_version_min(self):
  490         self.conf.config(group="api_settings", minimum_tls_version='TLSv1.2')
  491 
  492         # Test valid list
  493         validate.check_tls_version_min(['TLSv1.2', 'TLSv1.3'])
  494 
  495         # Test invalid list
  496         self.assertRaises(exceptions.ValidationException,
  497                           validate.check_tls_version_min,
  498                           ['TLSv1', 'TLSv1.1', 'TLSv1.2'])
  499 
  500     def test_check_default_tls_versions_min_conflict(self):
  501         self.conf.config(group="api_settings", minimum_tls_version='TLSv1.2')
  502 
  503         # Test conflict in listener default
  504         self.conf.config(group="api_settings", default_listener_tls_versions=[
  505                          'SSLv3', 'TLSv1.2'])
  506         self.assertRaises(exceptions.ValidationException,
  507                           validate.check_default_tls_versions_min_conflict)
  508 
  509         # Test conflict in pool default
  510         self.conf.config(group="api_settings", default_listener_tls_versions=[
  511                          'TLSv1.2'])
  512         self.conf.config(group="api_settings", default_pool_tls_versions=[
  513                          'TLSv1', 'TLSv1.3'])
  514         self.assertRaises(exceptions.ValidationException,
  515                           validate.check_default_tls_versions_min_conflict)
  516 
  517     def test_check_alpn_protocols(self):
  518         # Test valid list
  519         validate.check_alpn_protocols(['h2', 'http/1.1', 'http/1.0'])
  520         # Test invalid list
  521         self.assertRaises(
  522             exceptions.ValidationException,
  523             validate.check_alpn_protocols,
  524             ['httpie', 'foobar/1.2.3'])
  525         # Test empty list
  526         self.assertRaises(
  527             exceptions.ValidationException,
  528             validate.check_alpn_protocols,
  529             [])