mirror of
https://github.com/neondatabase/neon.git
synced 2026-08-12 09:19:39 +00:00
8075f0965a
# Problem While investigating #7124, I noticed that the benchmark was always using the `DEFAULT_*` `virtual_file_io_engine` , i.e., `tokio-epoll-uring` as of https://github.com/neondatabase/neon/pull/7077. The fundamental problem is that the `control_plane` code has its own view of `PageServerConfig`, which, I believe, will always be a subset of the real pageserver's `pageserver/src/config.rs`. For the `virtual_file_io_engine` and `get_vectored_impl` parametrization of the test suite, we were constructing a dict on the Python side that contained these parameters, then handed it to `control_plane::PageServerConfig`'s derived `serde::Deserialize`. The default in serde is to ignore unknown fields, so, the Deserialize impl silently ignored the fields. In consequence, the fields weren't propagated to the `pageserver --init` call, and the tests ended up using the `pageserver/src/config.rs::DEFAULT_` values for the respective options all the time. Tests that explicitly used overrides in `env.pageserver.start()` and similar were not affected by this. But, it means that all the test suite runs where with parametrization didn't properly exercise the code path. # Changes - use `serde(deny_unknown_fields)` to expose the problem - With this change, the Python tests that override `virtual_file_io_engine` and `get_vectored_impl` fail on `pageserver --init`, exposing the problem. - use destructuring to uncover the issue in the future - fix the issue by adding the missing fields to the `control_plane` crate's `PageServerConf` - A better solution would be for control plane to re-use a struct provided by the pageserver crate, so that everything is in one place in `pageserver/src/config.rs`, but, our config parsing code is (almost) beyond repair anyways. - fix the `pageserver_virtual_file_io_engine` to be responsive to the env var - => required to make parametrization work in benchmarks # Testing Before merging this PR, I re-ran the regression tests & CI with the full matrix of `virtual_file_io_engine` and `tokio-epoll-uring`, see https://github.com/neondatabase/neon/pull/7113/commits/9c7ea364e04835b894a33136ca26e0cdb8cd6e30
63 lines
1.8 KiB
Python
63 lines
1.8 KiB
Python
import os
|
|
from typing import Optional
|
|
|
|
import pytest
|
|
from _pytest.python import Metafunc
|
|
|
|
from fixtures.pg_version import PgVersion
|
|
|
|
"""
|
|
Dynamically parametrize tests by different parameters
|
|
"""
|
|
|
|
|
|
@pytest.fixture(scope="function", autouse=True)
|
|
def pg_version() -> Optional[PgVersion]:
|
|
return None
|
|
|
|
|
|
@pytest.fixture(scope="function", autouse=True)
|
|
def build_type() -> Optional[str]:
|
|
return None
|
|
|
|
|
|
@pytest.fixture(scope="function", autouse=True)
|
|
def platform() -> Optional[str]:
|
|
return None
|
|
|
|
|
|
@pytest.fixture(scope="function", autouse=True)
|
|
def pageserver_virtual_file_io_engine() -> Optional[str]:
|
|
return os.getenv("PAGESERVER_VIRTUAL_FILE_IO_ENGINE")
|
|
|
|
|
|
def pytest_generate_tests(metafunc: Metafunc):
|
|
if (bt := os.getenv("BUILD_TYPE")) is None:
|
|
build_types = ["debug", "release"]
|
|
else:
|
|
build_types = [bt.lower()]
|
|
|
|
metafunc.parametrize("build_type", build_types)
|
|
|
|
if (v := os.getenv("DEFAULT_PG_VERSION")) is None:
|
|
pg_versions = [version for version in PgVersion if version != PgVersion.NOT_SET]
|
|
else:
|
|
pg_versions = [PgVersion(v)]
|
|
|
|
metafunc.parametrize("pg_version", pg_versions, ids=map(lambda v: f"pg{v}", pg_versions))
|
|
|
|
# A hacky way to parametrize tests only for `pageserver_virtual_file_io_engine=std-fs`
|
|
# And do not change test name for default `pageserver_virtual_file_io_engine=tokio-epoll-uring` to keep tests statistics
|
|
if (io_engine := os.getenv("PAGESERVER_VIRTUAL_FILE_IO_ENGINE", "")) not in (
|
|
"",
|
|
"tokio-epoll-uring",
|
|
):
|
|
metafunc.parametrize("pageserver_virtual_file_io_engine", [io_engine])
|
|
|
|
# For performance tests, parametrize also by platform
|
|
if (
|
|
"test_runner/performance" in metafunc.definition._nodeid
|
|
and (platform := os.getenv("PLATFORM")) is not None
|
|
):
|
|
metafunc.parametrize("platform", [platform.lower()])
|