Skip to content

Commit 24f3f36

Browse files
committed
Merge branch 'master' into async-improvements
2 parents a23003f + a1ade45 commit 24f3f36

Some content is hidden

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

56 files changed

+3878
-520
lines changed

.evergreen/config.yml

Lines changed: 1237 additions & 302 deletions
Large diffs are not rendered by default.

.evergreen/hatch.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ else # Set up virtualenv before installing hatch
3434
fi
3535
export HATCH_CONFIG
3636
hatch config restore
37-
hatch config set dirs.data ".hatch/data"
38-
hatch config set dirs.cache ".hatch/cache"
37+
hatch config set dirs.data "$(pwd)/.hatch/data"
38+
hatch config set dirs.cache "$(pwd)/.hatch/cache"
3939

4040
run_hatch() {
4141
python -m hatch run "$@"

.evergreen/run-tests.sh

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ set -o xtrace
3030

3131
AUTH=${AUTH:-noauth}
3232
SSL=${SSL:-nossl}
33-
TEST_SUITES=""
33+
TEST_SUITES=${TEST_SUITES:-}
3434
TEST_ARGS="${*:1}"
3535

3636
export PIP_QUIET=1 # Quiet by default
@@ -90,6 +90,8 @@ if [ -n "$TEST_ENTERPRISE_AUTH" ]; then
9090
export GSSAPI_HOST=${SASL_HOST}
9191
export GSSAPI_PORT=${SASL_PORT}
9292
export GSSAPI_PRINCIPAL=${PRINCIPAL}
93+
94+
export TEST_SUITES="auth"
9395
fi
9496

9597
if [ -n "$TEST_LOADBALANCER" ]; then

.evergreen/scripts/generate_config.py

Lines changed: 297 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,23 @@
2323
##############
2424

2525
ALL_VERSIONS = ["4.0", "4.4", "5.0", "6.0", "7.0", "8.0", "rapid", "latest"]
26+
VERSIONS_6_0_PLUS = ["6.0", "7.0", "8.0", "rapid", "latest"]
2627
CPYTHONS = ["3.9", "3.10", "3.11", "3.12", "3.13"]
2728
PYPYS = ["pypy3.9", "pypy3.10"]
2829
ALL_PYTHONS = CPYTHONS + PYPYS
30+
MIN_MAX_PYTHON = [CPYTHONS[0], CPYTHONS[-1]]
2931
BATCHTIME_WEEK = 10080
32+
AUTH_SSLS = [("auth", "ssl"), ("noauth", "ssl"), ("noauth", "nossl")]
33+
TOPOLOGIES = ["standalone", "replica_set", "sharded_cluster"]
34+
C_EXTS = ["with_ext", "without_ext"]
35+
SYNCS = ["sync", "async"]
36+
DISPLAY_LOOKUP = dict(
37+
ssl=dict(ssl="SSL", nossl="NoSSL"),
38+
auth=dict(auth="Auth", noauth="NoAuth"),
39+
test_suites=dict(default="Sync", default_async="Async"),
40+
coverage=dict(coverage="cov"),
41+
no_ext={"1": "No C"},
42+
)
3043
HOSTS = dict()
3144

3245

@@ -39,7 +52,9 @@ class Host:
3952

4053
HOSTS["rhel8"] = Host("rhel8", "rhel87-small", "RHEL8")
4154
HOSTS["win64"] = Host("win64", "windows-64-vsMulti-small", "Win64")
55+
HOSTS["win32"] = Host("win32", "windows-64-vsMulti-small", "Win32")
4256
HOSTS["macos"] = Host("macos", "macos-14", "macOS")
57+
HOSTS["macos-arm64"] = Host("macos-arm64", "macos-14-arm64", "macOS Arm64")
4358

4459

4560
##############
@@ -80,10 +95,8 @@ def create_variant(
8095

8196
def get_python_binary(python: str, host: str) -> str:
8297
"""Get the appropriate python binary given a python version and host."""
83-
if host == "win64":
84-
is_32 = python.startswith("32-bit")
85-
if is_32:
86-
_, python = python.split()
98+
if host in ["win64", "win32"]:
99+
if host == "win32":
87100
base = "C:/python/32"
88101
else:
89102
base = "C:/python"
@@ -93,19 +106,31 @@ def get_python_binary(python: str, host: str) -> str:
93106
if host == "rhel8":
94107
return f"/opt/python/{python}/bin/python3"
95108

96-
if host == "macos":
109+
if host in ["macos", "macos-arm64"]:
97110
return f"/Library/Frameworks/Python.Framework/Versions/{python}/bin/python3"
98111

99112
raise ValueError(f"no match found for python {python} on {host}")
100113

101114

102-
def get_display_name(base: str, host: str, version: str, python: str) -> str:
115+
def get_display_name(base: str, host: str, **kwargs) -> str:
103116
"""Get the display name of a variant."""
104-
if version not in ["rapid", "latest"]:
105-
version = f"v{version}"
106-
if not python.startswith("pypy"):
107-
python = f"py{python}"
108-
return f"{base} {HOSTS[host].display_name} {version} {python}"
117+
display_name = f"{base} {HOSTS[host].display_name}"
118+
version = kwargs.pop("VERSION", None)
119+
if version:
120+
if version not in ["rapid", "latest"]:
121+
version = f"v{version}"
122+
display_name = f"{display_name} {version}"
123+
for key, value in kwargs.items():
124+
name = value
125+
if key.lower() == "python":
126+
if not value.startswith("pypy"):
127+
name = f"py{value}"
128+
elif key.lower() in DISPLAY_LOOKUP:
129+
name = DISPLAY_LOOKUP[key.lower()][value]
130+
else:
131+
continue
132+
display_name = f"{display_name} {name}"
133+
return display_name
109134

110135

111136
def zip_cycle(*iterables, empty_default=None):
@@ -115,6 +140,21 @@ def zip_cycle(*iterables, empty_default=None):
115140
yield tuple(next(i, empty_default) for i in cycles)
116141

117142

143+
def handle_c_ext(c_ext, expansions):
144+
"""Handle c extension option."""
145+
if c_ext == C_EXTS[0]:
146+
expansions["NO_EXT"] = "1"
147+
148+
149+
def generate_yaml(tasks=None, variants=None):
150+
"""Generate the yaml for a given set of tasks and variants."""
151+
project = EvgProject(tasks=tasks, buildvariants=variants)
152+
out = ShrubService.generate_yaml(project)
153+
# Dedent by two spaces to match what we use in config.yml
154+
lines = [line[2:] for line in out.splitlines()]
155+
print("\n".join(lines)) # noqa: T201
156+
157+
118158
##############
119159
# Variants
120160
##############
@@ -159,9 +199,253 @@ def create_ocsp_variants() -> list[BuildVariant]:
159199
return variants
160200

161201

202+
def create_server_variants() -> list[BuildVariant]:
203+
variants = []
204+
205+
# Run the full matrix on linux with min and max CPython, and latest pypy.
206+
host = "rhel8"
207+
for python, (auth, ssl) in product([*MIN_MAX_PYTHON, PYPYS[-1]], AUTH_SSLS):
208+
display_name = f"Test {host}"
209+
expansions = dict(AUTH=auth, SSL=ssl, COVERAGE="coverage")
210+
display_name = get_display_name("Test", host, python=python, **expansions)
211+
variant = create_variant(
212+
[f".{t}" for t in TOPOLOGIES],
213+
display_name,
214+
python=python,
215+
host=host,
216+
tags=["coverage_tag"],
217+
expansions=expansions,
218+
)
219+
variants.append(variant)
220+
221+
# Test the rest of the pythons on linux.
222+
for python, (auth, ssl), topology in zip_cycle(
223+
CPYTHONS[1:-1] + PYPYS[:-1], AUTH_SSLS, TOPOLOGIES
224+
):
225+
display_name = f"Test {host}"
226+
expansions = dict(AUTH=auth, SSL=ssl)
227+
display_name = get_display_name("Test", host, python=python, **expansions)
228+
variant = create_variant(
229+
[f".{topology}"],
230+
display_name,
231+
python=python,
232+
host=host,
233+
expansions=expansions,
234+
)
235+
variants.append(variant)
236+
237+
# Test a subset on each of the other platforms.
238+
for host in ("macos", "macos-arm64", "win64", "win32"):
239+
for (python, (auth, ssl), topology), sync in product(
240+
zip_cycle(MIN_MAX_PYTHON, AUTH_SSLS, TOPOLOGIES), SYNCS
241+
):
242+
test_suite = "default" if sync == "sync" else "default_async"
243+
tasks = [f".{topology}"]
244+
# MacOS arm64 only works on server versions 6.0+
245+
if host == "macos-arm64":
246+
tasks = [f".{topology} .{version}" for version in VERSIONS_6_0_PLUS]
247+
expansions = dict(AUTH=auth, SSL=ssl, TEST_SUITES=test_suite, SKIP_CSOT_TESTS="true")
248+
display_name = get_display_name("Test", host, python=python, **expansions)
249+
variant = create_variant(
250+
tasks,
251+
display_name,
252+
python=python,
253+
host=host,
254+
expansions=expansions,
255+
)
256+
variants.append(variant)
257+
258+
return variants
259+
260+
261+
def create_encryption_variants() -> list[BuildVariant]:
262+
variants = []
263+
tags = ["encryption_tag"]
264+
batchtime = BATCHTIME_WEEK
265+
266+
def get_encryption_expansions(encryption, ssl="ssl"):
267+
expansions = dict(AUTH="auth", SSL=ssl, test_encryption="true")
268+
if "crypt_shared" in encryption:
269+
expansions["test_crypt_shared"] = "true"
270+
if "PyOpenSSL" in encryption:
271+
expansions["test_encryption_pyopenssl"] = "true"
272+
return expansions
273+
274+
host = "rhel8"
275+
276+
# Test against all server versions and topolgies for the three main python versions.
277+
encryptions = ["Encryption", "Encryption crypt_shared", "Encryption PyOpenSSL"]
278+
for encryption, python in product(encryptions, [*MIN_MAX_PYTHON, PYPYS[-1]]):
279+
expansions = get_encryption_expansions(encryption)
280+
display_name = get_display_name(encryption, host, python=python, **expansions)
281+
variant = create_variant(
282+
[f".{t}" for t in TOPOLOGIES],
283+
display_name,
284+
python=python,
285+
host=host,
286+
expansions=expansions,
287+
batchtime=batchtime,
288+
tags=tags,
289+
)
290+
variants.append(variant)
291+
292+
# Test the rest of the pythons on linux for all server versions.
293+
for encryption, python, ssl in zip_cycle(
294+
encryptions, CPYTHONS[1:-1] + PYPYS[:-1], ["ssl", "nossl"]
295+
):
296+
expansions = get_encryption_expansions(encryption, ssl)
297+
display_name = get_display_name(encryption, host, python=python, **expansions)
298+
variant = create_variant(
299+
[".replica_set"],
300+
display_name,
301+
python=python,
302+
host=host,
303+
expansions=expansions,
304+
)
305+
variants.append(variant)
306+
307+
# Test on macos and linux on one server version and topology for min and max python.
308+
encryptions = ["Encryption", "Encryption crypt_shared"]
309+
task_names = [".latest .replica_set"]
310+
for host, encryption, python in product(["macos", "win64"], encryptions, MIN_MAX_PYTHON):
311+
ssl = "ssl" if python == CPYTHONS[0] else "nossl"
312+
expansions = get_encryption_expansions(encryption, ssl)
313+
display_name = get_display_name(encryption, host, python=python, **expansions)
314+
variant = create_variant(
315+
task_names,
316+
display_name,
317+
python=python,
318+
host=host,
319+
expansions=expansions,
320+
batchtime=batchtime,
321+
tags=tags,
322+
)
323+
variants.append(variant)
324+
return variants
325+
326+
327+
def create_load_balancer_variants():
328+
# Load balancer tests - run all supported versions for all combinations of auth and ssl and system python.
329+
host = "rhel8"
330+
task_names = ["load-balancer-test"]
331+
batchtime = BATCHTIME_WEEK
332+
expansions_base = dict(test_loadbalancer="true")
333+
versions = ["6.0", "7.0", "8.0", "latest", "rapid"]
334+
variants = []
335+
pythons = CPYTHONS + PYPYS
336+
for ind, (version, (auth, ssl)) in enumerate(product(versions, AUTH_SSLS)):
337+
expansions = dict(VERSION=version, AUTH=auth, SSL=ssl)
338+
expansions.update(expansions_base)
339+
python = pythons[ind % len(pythons)]
340+
display_name = get_display_name("Load Balancer", host, python=python, **expansions)
341+
variant = create_variant(
342+
task_names,
343+
display_name,
344+
python=python,
345+
host=host,
346+
expansions=expansions,
347+
batchtime=batchtime,
348+
)
349+
variants.append(variant)
350+
return variants
351+
352+
353+
def create_compression_variants():
354+
# Compression tests - standalone versions of each server, across python versions, with and without c extensions.
355+
# PyPy interpreters are always tested without extensions.
356+
host = "rhel8"
357+
task_names = dict(snappy=[".standalone"], zlib=[".standalone"], zstd=[".standalone !.4.0"])
358+
variants = []
359+
for ind, (compressor, c_ext) in enumerate(product(["snappy", "zlib", "zstd"], C_EXTS)):
360+
expansions = dict(COMPRESSORS=compressor)
361+
handle_c_ext(c_ext, expansions)
362+
base_name = f"{compressor} compression"
363+
python = CPYTHONS[ind % len(CPYTHONS)]
364+
display_name = get_display_name(base_name, host, python=python, **expansions)
365+
variant = create_variant(
366+
task_names[compressor],
367+
display_name,
368+
python=python,
369+
host=host,
370+
expansions=expansions,
371+
)
372+
variants.append(variant)
373+
374+
other_pythons = PYPYS + CPYTHONS[ind:]
375+
for compressor, python in zip_cycle(["snappy", "zlib", "zstd"], other_pythons):
376+
expansions = dict(COMPRESSORS=compressor)
377+
handle_c_ext(c_ext, expansions)
378+
base_name = f"{compressor} compression"
379+
display_name = get_display_name(base_name, host, python=python, **expansions)
380+
variant = create_variant(
381+
task_names[compressor],
382+
display_name,
383+
python=python,
384+
host=host,
385+
expansions=expansions,
386+
)
387+
variants.append(variant)
388+
389+
return variants
390+
391+
392+
def create_enterprise_auth_variants():
393+
expansions = dict(AUTH="auth")
394+
variants = []
395+
396+
# All python versions across platforms.
397+
for python in ALL_PYTHONS:
398+
if python == CPYTHONS[0]:
399+
host = "macos"
400+
elif python == CPYTHONS[-1]:
401+
host = "win64"
402+
else:
403+
host = "rhel8"
404+
display_name = get_display_name("Enterprise Auth", host, python=python, **expansions)
405+
variant = create_variant(
406+
["test-enterprise-auth"], display_name, host=host, python=python, expansions=expansions
407+
)
408+
variants.append(variant)
409+
410+
return variants
411+
412+
413+
def create_pyopenssl_variants():
414+
base_name = "PyOpenSSL"
415+
batchtime = BATCHTIME_WEEK
416+
base_expansions = dict(test_pyopenssl="true", SSL="ssl")
417+
variants = []
418+
419+
for python in ALL_PYTHONS:
420+
# Only test "noauth" with min python.
421+
auth = "noauth" if python == CPYTHONS[0] else "auth"
422+
if python == CPYTHONS[0]:
423+
host = "macos"
424+
elif python == CPYTHONS[-1]:
425+
host = "win64"
426+
else:
427+
host = "rhel8"
428+
expansions = dict(AUTH=auth)
429+
expansions.update(base_expansions)
430+
431+
display_name = get_display_name(base_name, host, python=python)
432+
variant = create_variant(
433+
[".replica_set", ".7.0"],
434+
display_name,
435+
python=python,
436+
host=host,
437+
expansions=expansions,
438+
batchtime=batchtime,
439+
)
440+
variants.append(variant)
441+
442+
return variants
443+
444+
162445
##################
163446
# Generate Config
164447
##################
165448

166-
project = EvgProject(tasks=None, buildvariants=create_ocsp_variants())
167-
print(ShrubService.generate_yaml(project)) # noqa: T201
449+
variants = create_pyopenssl_variants()
450+
# print(len(variants))
451+
generate_yaml(variants=variants)

0 commit comments

Comments
 (0)