...

Text file src/go.mongodb.org/mongo-driver/testdata/server-discovery-and-monitoring/errors/generate-error-tests.py

Documentation: go.mongodb.org/mongo-driver/testdata/server-discovery-and-monitoring/errors

     1import itertools
     2import os
     3import subprocess
     4import sys
     5
     6# Require Python 3.7+ for ordered dictionaries so that the order of the
     7# generated tests remain the same.
     8if sys.version_info[:2] < (3, 7):
     9    print('ERROR: This script requires Python >= 3.7, not:')
    10    print(sys.version)
    11    print('Usage: python3 %s' % (sys.argv[0]))
    12    exit(1)
    13
    14
    15dirname = os.path.dirname
    16DIR = dirname(os.path.realpath(__file__))
    17SOURCE = dirname(dirname(dirname(DIR)))
    18
    19
    20def template(filename):
    21    fullpath = os.path.join(DIR, filename)
    22    with open(fullpath, 'r') as f:
    23        return f.read()
    24
    25
    26def write_test(filename, data):
    27    fullpath = os.path.join(DIR, filename + '.yml')
    28    with open(fullpath, 'w') as f:
    29        f.write(data)
    30
    31    print(f"Generated {fullpath}")
    32
    33
    34# Maps from error_name to (error_code,)
    35ERR_CODES = {
    36    'InterruptedAtShutdown': (11600,),
    37    'InterruptedDueToReplStateChange': (11602,),
    38    'NotPrimaryOrSecondary': (13436,),
    39    'PrimarySteppedDown': (189,),
    40    'ShutdownInProgress': (91,),
    41    'NotWritablePrimary': (10107,),
    42    'NotPrimaryNoSecondaryOk': (13435,),
    43    'LegacyNotPrimary': (10058,),
    44}
    45
    46
    47def create_stale_tests():
    48    tmp = template('stale-topologyVersion.yml.template')
    49    for error_name in ERR_CODES:
    50        test_name = f'stale-topologyVersion-{error_name}'
    51        error_code, = ERR_CODES[error_name]
    52        data = tmp.format(**locals())
    53        write_test(test_name, data)
    54
    55TV_GREATER = '''
    56      topologyVersion:
    57        processId:
    58          "$oid": '000000000000000000000001'
    59        counter:
    60          "$numberLong": "2"'''
    61TV_GREATER_FINAL =  '''
    62          processId:
    63            "$oid": '000000000000000000000001'
    64          counter:
    65            "$numberLong": "2"'''
    66TV_CHANGED = '''
    67      topologyVersion:
    68        processId:
    69          "$oid": '000000000000000000000002'
    70        counter:
    71          "$numberLong": "1"'''
    72TV_CHANGED_FINAL =  '''
    73          processId:
    74            "$oid": '000000000000000000000002'
    75          counter:
    76            "$numberLong": "1"'''
    77
    78# Maps non-stale error description to:
    79# (error_topology_version, final_topology_version)
    80NON_STALE_CASES = {
    81    'topologyVersion missing': ('', ' null'),
    82    'topologyVersion greater': (TV_GREATER, TV_GREATER_FINAL),
    83    'topologyVersion proccessId changed': (TV_CHANGED, TV_CHANGED_FINAL),
    84}
    85
    86
    87def create_non_stale_tests():
    88    tmp = template('non-stale-topologyVersion.yml.template')
    89    for error_name, description in itertools.product(
    90            ERR_CODES, NON_STALE_CASES):
    91        test_name = f'non-stale-{description.replace(" ", "-")}-{error_name}'
    92        error_code, = ERR_CODES[error_name]
    93        error_topology_version, final_topology_version = NON_STALE_CASES[description]
    94        # On 4.2+, only ShutdownInProgress and InterruptedAtShutdown will
    95        # clear the pool.
    96        if error_name in ("ShutdownInProgress", "InterruptedAtShutdown"):
    97            final_pool_generation = 1
    98        else:
    99            final_pool_generation = 0
   100
   101        data = tmp.format(**locals())
   102        write_test(test_name, data)
   103
   104
   105WHEN = ['beforeHandshakeCompletes', 'afterHandshakeCompletes']
   106STALE_GENERATION_COMMAND_ERROR = '''
   107    type: command
   108    response:
   109      ok: 0
   110      errmsg: {error_name}
   111      code: {error_code}
   112      topologyVersion:
   113        processId:
   114          "$oid": '000000000000000000000001'
   115        counter:
   116          "$numberLong": "2"'''
   117STALE_GENERATION_NETWORK_ERROR = '''
   118    type: {network_error_type}'''
   119
   120
   121def create_stale_generation_tests():
   122    tmp = template('stale-generation.yml.template')
   123    # Stale command errors
   124    for error_name, when in itertools.product(ERR_CODES, WHEN):
   125        test_name = f'stale-generation-{when}-{error_name}'
   126        error_code, = ERR_CODES[error_name]
   127        stale_error = STALE_GENERATION_COMMAND_ERROR.format(**locals())
   128        data = tmp.format(**locals())
   129        write_test(test_name, data)
   130    # Stale network errors
   131    for network_error_type, when in itertools.product(
   132            ['network', 'timeout'], WHEN):
   133        error_name = network_error_type
   134        test_name = f'stale-generation-{when}-{network_error_type}'
   135        stale_error = STALE_GENERATION_NETWORK_ERROR.format(**locals())
   136        data = tmp.format(**locals())
   137        write_test(test_name, data)
   138
   139
   140def create_pre_42_tests():
   141    tmp = template('pre-42.yml.template')
   142    # All "not writable primary"/"node is recovering" clear the pool on <4.2
   143    for error_name in ERR_CODES:
   144        test_name = f'pre-42-{error_name}'
   145        error_code, = ERR_CODES[error_name]
   146        data = tmp.format(**locals())
   147        write_test(test_name, data)
   148
   149
   150def create_post_42_tests():
   151    tmp = template('post-42.yml.template')
   152    for error_name in ERR_CODES:
   153        test_name = f'post-42-{error_name}'
   154        error_code, = ERR_CODES[error_name]
   155        # On 4.2+, only ShutdownInProgress and InterruptedAtShutdown will
   156        # clear the pool.
   157        if error_name in ("ShutdownInProgress", "InterruptedAtShutdown"):
   158            final_pool_generation = 1
   159        else:
   160            final_pool_generation = 0
   161        data = tmp.format(**locals())
   162        write_test(test_name, data)
   163
   164
   165create_stale_tests()
   166create_non_stale_tests()
   167create_stale_generation_tests()
   168create_pre_42_tests()
   169create_post_42_tests()
   170
   171print('Running make')
   172subprocess.run(f'cd {SOURCE} && make', shell=True, check=True)

View as plain text