Skip to content

Commit 2b67ddc

Browse files
iwysiuDivjot Arora
authored andcommitted
1 parent 324f6a9 commit 2b67ddc

File tree

151 files changed

+13770
-100
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

151 files changed

+13770
-100
lines changed
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
{
2+
"description": "Network timeouts before and after the handshake completes",
3+
"uri": "mongodb://a/?replicaSet=rs",
4+
"phases": [
5+
{
6+
"description": "Primary A is discovered",
7+
"responses": [
8+
[
9+
"a:27017",
10+
{
11+
"ok": 1,
12+
"ismaster": true,
13+
"hosts": [
14+
"a:27017"
15+
],
16+
"setName": "rs",
17+
"minWireVersion": 0,
18+
"maxWireVersion": 9,
19+
"topologyVersion": {
20+
"processId": {
21+
"$oid": "000000000000000000000001"
22+
},
23+
"counter": {
24+
"$numberLong": "1"
25+
}
26+
}
27+
}
28+
]
29+
],
30+
"outcome": {
31+
"servers": {
32+
"a:27017": {
33+
"type": "RSPrimary",
34+
"setName": "rs",
35+
"topologyVersion": {
36+
"processId": {
37+
"$oid": "000000000000000000000001"
38+
},
39+
"counter": {
40+
"$numberLong": "1"
41+
}
42+
},
43+
"pool": {
44+
"generation": 0
45+
}
46+
}
47+
},
48+
"topologyType": "ReplicaSetWithPrimary",
49+
"logicalSessionTimeoutMinutes": null,
50+
"setName": "rs"
51+
}
52+
},
53+
{
54+
"description": "Ignore network timeout application error (afterHandshakeCompletes)",
55+
"applicationErrors": [
56+
{
57+
"address": "a:27017",
58+
"when": "afterHandshakeCompletes",
59+
"maxWireVersion": 9,
60+
"type": "timeout"
61+
}
62+
],
63+
"outcome": {
64+
"servers": {
65+
"a:27017": {
66+
"type": "RSPrimary",
67+
"setName": "rs",
68+
"topologyVersion": {
69+
"processId": {
70+
"$oid": "000000000000000000000001"
71+
},
72+
"counter": {
73+
"$numberLong": "1"
74+
}
75+
},
76+
"pool": {
77+
"generation": 0
78+
}
79+
}
80+
},
81+
"topologyType": "ReplicaSetWithPrimary",
82+
"logicalSessionTimeoutMinutes": null,
83+
"setName": "rs"
84+
}
85+
},
86+
{
87+
"description": "Mark server unknown on network timeout application error (beforeHandshakeCompletes)",
88+
"applicationErrors": [
89+
{
90+
"address": "a:27017",
91+
"when": "beforeHandshakeCompletes",
92+
"maxWireVersion": 9,
93+
"type": "timeout"
94+
}
95+
],
96+
"outcome": {
97+
"servers": {
98+
"a:27017": {
99+
"type": "Unknown",
100+
"topologyVersion": null,
101+
"pool": {
102+
"generation": 1
103+
}
104+
}
105+
},
106+
"topologyType": "ReplicaSetNoPrimary",
107+
"logicalSessionTimeoutMinutes": null,
108+
"setName": "rs"
109+
}
110+
}
111+
]
112+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
description: Network timeouts before and after the handshake completes
2+
uri: mongodb://a/?replicaSet=rs
3+
phases:
4+
- description: Primary A is discovered
5+
responses:
6+
- - a:27017
7+
- ok: 1
8+
ismaster: true
9+
hosts:
10+
- a:27017
11+
setName: rs
12+
minWireVersion: 0
13+
maxWireVersion: 9
14+
topologyVersion: &topologyVersion_1_1
15+
processId:
16+
"$oid": '000000000000000000000001'
17+
counter:
18+
"$numberLong": '1'
19+
outcome: &outcome
20+
servers:
21+
a:27017:
22+
type: RSPrimary
23+
setName: rs
24+
topologyVersion: *topologyVersion_1_1
25+
pool:
26+
generation: 0
27+
topologyType: ReplicaSetWithPrimary
28+
logicalSessionTimeoutMinutes: null
29+
setName: rs
30+
31+
- description: Ignore network timeout application error (afterHandshakeCompletes)
32+
applicationErrors:
33+
- address: a:27017
34+
when: afterHandshakeCompletes
35+
maxWireVersion: 9
36+
type: timeout
37+
outcome: *outcome
38+
39+
- description: Mark server unknown on network timeout application error (beforeHandshakeCompletes)
40+
applicationErrors:
41+
- address: a:27017
42+
when: beforeHandshakeCompletes
43+
maxWireVersion: 9
44+
type: timeout
45+
outcome:
46+
servers:
47+
a:27017:
48+
type: Unknown
49+
topologyVersion: null
50+
pool:
51+
generation: 1
52+
topologyType: ReplicaSetNoPrimary
53+
logicalSessionTimeoutMinutes: null
54+
setName: rs
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
import itertools
2+
import os
3+
import subprocess
4+
import sys
5+
6+
# Require Python 3.7+ for ordered dictionaries so that the order of the
7+
# generated tests remain the same.
8+
if 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+
15+
dirname = os.path.dirname
16+
DIR = dirname(os.path.realpath(__file__))
17+
SOURCE = dirname(dirname(dirname(DIR)))
18+
19+
20+
def template(filename):
21+
fullpath = os.path.join(DIR, filename)
22+
with open(fullpath, 'r') as f:
23+
return f.read()
24+
25+
26+
def 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,)
35+
ERR_CODES = {
36+
'InterruptedAtShutdown': (11600,),
37+
'InterruptedDueToReplStateChange': (11602,),
38+
'NotMasterOrSecondary': (13436,),
39+
'PrimarySteppedDown': (189,),
40+
'ShutdownInProgress': (91,),
41+
'NotMaster': (10107,),
42+
'NotMasterNoSlaveOk': (13435,),
43+
}
44+
45+
46+
def create_stale_tests():
47+
tmp = template('stale-topologyVersion.yml.template')
48+
for error_name in ERR_CODES:
49+
test_name = f'stale-topologyVersion-{error_name}'
50+
error_code, = ERR_CODES[error_name]
51+
data = tmp.format(**locals())
52+
write_test(test_name, data)
53+
54+
TV_GREATER = '''
55+
topologyVersion:
56+
processId:
57+
"$oid": '000000000000000000000001'
58+
counter:
59+
"$numberLong": "2"'''
60+
TV_GREATER_FINAL = '''
61+
processId:
62+
"$oid": '000000000000000000000001'
63+
counter:
64+
"$numberLong": "2"'''
65+
TV_CHANGED = '''
66+
topologyVersion:
67+
processId:
68+
"$oid": '000000000000000000000002'
69+
counter:
70+
"$numberLong": "1"'''
71+
TV_CHANGED_FINAL = '''
72+
processId:
73+
"$oid": '000000000000000000000002'
74+
counter:
75+
"$numberLong": "1"'''
76+
77+
# Maps non-stale error description to:
78+
# (error_topology_version, final_topology_version)
79+
NON_STALE_CASES = {
80+
'topologyVersion missing': ('', ' null'),
81+
'topologyVersion greater': (TV_GREATER, TV_GREATER_FINAL),
82+
'topologyVersion proccessId changed': (TV_CHANGED, TV_CHANGED_FINAL),
83+
}
84+
85+
86+
def create_non_stale_tests():
87+
tmp = template('non-stale-topologyVersion.yml.template')
88+
for error_name, description in itertools.product(
89+
ERR_CODES, NON_STALE_CASES):
90+
test_name = f'non-stale-{description.replace(" ", "-")}-{error_name}'
91+
error_code, = ERR_CODES[error_name]
92+
error_topology_version, final_topology_version = NON_STALE_CASES[description]
93+
# On 4.2+, only ShutdownInProgress and InterruptedAtShutdown will
94+
# clear the pool.
95+
if error_name in ("ShutdownInProgress", "InterruptedAtShutdown"):
96+
final_pool_generation = 1
97+
else:
98+
final_pool_generation = 0
99+
100+
data = tmp.format(**locals())
101+
write_test(test_name, data)
102+
103+
104+
WHEN = ['beforeHandshakeCompletes', 'afterHandshakeCompletes']
105+
STALE_GENERATION_COMMAND_ERROR = '''
106+
type: command
107+
response:
108+
ok: 0
109+
errmsg: {error_name}
110+
code: {error_code}
111+
topologyVersion:
112+
processId:
113+
"$oid": '000000000000000000000001'
114+
counter:
115+
"$numberLong": "2"'''
116+
STALE_GENERATION_NETWORK_ERROR = '''
117+
type: {network_error_type}'''
118+
119+
120+
def create_stale_generation_tests():
121+
tmp = template('stale-generation.yml.template')
122+
# Stale command errors
123+
for error_name, when in itertools.product(ERR_CODES, WHEN):
124+
test_name = f'stale-generation-{when}-{error_name}'
125+
error_code, = ERR_CODES[error_name]
126+
stale_error = STALE_GENERATION_COMMAND_ERROR.format(**locals())
127+
data = tmp.format(**locals())
128+
write_test(test_name, data)
129+
# Stale network errors
130+
for network_error_type, when in itertools.product(
131+
['network', 'timeout'], WHEN):
132+
test_name = f'stale-generation-{when}-{network_error_type}'
133+
stale_error = STALE_GENERATION_NETWORK_ERROR.format(**locals())
134+
data = tmp.format(**locals())
135+
write_test(test_name, data)
136+
137+
138+
def create_pre_42_tests():
139+
tmp = template('pre-42.yml.template')
140+
# All "not master"/"node is recovering" clear the pool on <4.2
141+
for error_name in ERR_CODES:
142+
test_name = f'pre-42-{error_name}'
143+
error_code, = ERR_CODES[error_name]
144+
data = tmp.format(**locals())
145+
write_test(test_name, data)
146+
147+
148+
def create_post_42_tests():
149+
tmp = template('post-42.yml.template')
150+
for error_name in ERR_CODES:
151+
test_name = f'pre-42-{error_name}'
152+
error_code, = ERR_CODES[error_name]
153+
# On 4.2+, only ShutdownInProgress and InterruptedAtShutdown will
154+
# clear the pool.
155+
if error_name in ("ShutdownInProgress", "InterruptedAtShutdown"):
156+
final_pool_generation = 1
157+
else:
158+
final_pool_generation = 0
159+
data = tmp.format(**locals())
160+
write_test(test_name, data)
161+
162+
163+
create_stale_tests()
164+
create_non_stale_tests()
165+
create_stale_generation_tests()
166+
create_pre_42_tests()
167+
create_post_42_tests()
168+
169+
print('Running make')
170+
subprocess.run(f'cd {SOURCE} && make', shell=True, check=True)

0 commit comments

Comments
 (0)