Skip to content

Commit c284a42

Browse files
committed
TestKit time-warp backend
1 parent 6ea4c12 commit c284a42

File tree

11 files changed

+229
-38
lines changed

11 files changed

+229
-38
lines changed

.dockerignore

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,3 @@ dist
44
venv*/
55
.coverage
66
tests/
7-
testkit/
8-
testkitbackend/

testkit/Dockerfile

Lines changed: 81 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,71 @@
1-
FROM ubuntu:20.04
1+
ARG TIME_WARP=""
2+
FROM ubuntu:20.04 AS base
3+
ARG TIME_WARP
24

35
ENV DEBIAN_FRONTEND=noninteractive
46
RUN apt-get update && \
57
apt-get install -y locales && \
6-
apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* && \
7-
localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8 \
8-
&& rm -rf /var/lib/apt/lists/*
8+
localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8 && \
9+
apt-get clean && \
10+
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
911
ENV LANG=en_US.UTF-8
1012

1113
# Using apt-get update alone in a RUN statement causes caching issues and subsequent apt-get install instructions fail.
12-
RUN apt-get --quiet update && apt-get --quiet install -y \
13-
software-properties-common \
14-
bash \
15-
python3 \
16-
python3-pip \
17-
git \
18-
curl \
19-
tar \
20-
wget \
21-
&& rm -rf /var/lib/apt/lists/*
14+
RUN apt-get update && \
15+
apt-get install -y \
16+
software-properties-common \
17+
bash \
18+
python3 \
19+
python3-pip \
20+
git \
21+
curl \
22+
tar \
23+
wget && \
24+
apt-get clean && \
25+
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
2226

2327
# Install Build Tools
2428
RUN apt-get update && \
2529
apt-get install -y --no-install-recommends \
26-
make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev \
27-
libsqlite3-dev wget curl llvm libncurses5-dev xz-utils tk-dev \
28-
libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev \
30+
make \
31+
build-essential \
32+
libssl-dev \
33+
zlib1g-dev \
34+
libbz2-dev \
35+
libreadline-dev\
36+
libsqlite3-dev \
37+
wget \
38+
curl \
39+
llvm \
40+
libncurses5-dev \
41+
xz-utils \
42+
tk-dev\
43+
libxml2-dev \
44+
libxmlsec1-dev \
45+
libffi-dev \
46+
liblzma-dev\
2947
ca-certificates && \
30-
apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
31-
32-
# Install our own CAs on the image.
33-
# Assumes Linux Debian based image.
34-
COPY CAs/* /usr/local/share/ca-certificates/
35-
# Store custom CAs somewhere where the backend can find them later.
36-
COPY CustomCAs/* /usr/local/share/custom-ca-certificates/
37-
RUN update-ca-certificates
48+
apt-get clean && \
49+
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
3850

3951
# Install pyenv
4052
RUN git clone https://github.com/pyenv/pyenv.git .pyenv
4153
ENV PYENV_ROOT=/.pyenv
4254
ENV PATH="$PYENV_ROOT/shims:$PYENV_ROOT/bin:$PATH"
55+
ENV PIP_NO_CACHE_DIR=1
4356

44-
# Setup python version
45-
ENV PYTHON_VERSIONS="3.13 3.12 3.11 3.10"
57+
58+
FROM base AS base-py-arg
59+
# Install all supported Python versions
60+
ARG PYTHON_VERSIONS="3.13 3.12 3.11 3.10"
61+
62+
63+
FROM base AS base-py-arg-single-python
64+
# Only install Python 3.10 in time warp mode
65+
ARG PYTHON_VERSIONS="3.10"
66+
67+
68+
FROM base-py-arg${TIME_WARP:+"-single-python"} AS base-py-install
4669

4770
RUN for version in $PYTHON_VERSIONS; do \
4871
pyenv install $version; \
@@ -56,3 +79,34 @@ RUN pyenv global $(pyenv versions --bare --skip-aliases | sort --version-sort --
5679
RUN for version in $PYTHON_VERSIONS; do \
5780
python$version -m pip install -U pip; \
5881
done
82+
83+
ENV DRIVER_TIME_WARP=$TIME_WARP
84+
85+
86+
FROM base-py-install AS backend-timewarp
87+
WORKDIR /home/root/testkit
88+
89+
COPY testkit/backend.py testkit/build.py testkit/_common.py testkit/
90+
COPY pyproject.toml .
91+
92+
RUN for version in $PYTHON_VERSIONS; do \
93+
TEST_BACKEND_VERSION="python$version" python testkit/build.py && \
94+
python$version -m pip install --force-reinstall neo4j==${TIME_WARP}; \
95+
done
96+
COPY testkitbackend ./testkitbackend
97+
ENTRYPOINT ["python", "testkit/backend.py"]
98+
99+
100+
FROM base-py-install AS backend
101+
102+
# Install our own CAs on the image.
103+
# Assumes Linux Debian based image.
104+
COPY CAs/* /usr/local/share/ca-certificates/
105+
# Store custom CAs somewhere where the backend can find them later.
106+
COPY CustomCAs/* /usr/local/share/custom-ca-certificates/
107+
RUN update-ca-certificates
108+
109+
110+
FROM backend${TIME_WARP:+"-timewarp"} AS final
111+
WORKDIR /home/root/testkit
112+
EXPOSE 9876/tcp

testkit/_common.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222

2323
TEST_BACKEND_VERSION = os.getenv("TEST_BACKEND_VERSION", "python")
24+
DRIVER_TIME_WARP = os.getenv("DRIVER_TIME_WARP")
2425

2526

2627
def run(args, env=None):

testkit/backend.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,5 @@
2323
cmd = ["-m", "testkitbackend"]
2424
if "TEST_BACKEND_SERVER" in os.environ:
2525
cmd.append(os.environ["TEST_BACKEND_SERVER"])
26-
run_python(cmd)
26+
is_time_warp = bool(os.environ.get("DRIVER_TIME_WARP"))
27+
run_python(cmd, warning_as_error=not is_time_warp)

testkit/build.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,22 @@
1616

1717
"""Building driver and test backend inside driver container."""
1818

19-
from _common import run_python
19+
import sys
20+
21+
from _common import (
22+
DRIVER_TIME_WARP,
23+
run_python,
24+
)
2025

2126

2227
if __name__ == "__main__":
28+
if DRIVER_TIME_WARP:
29+
run_python(
30+
["-m", "pip", "install", "-U", "--group", "testkit"],
31+
warning_as_error=False,
32+
)
33+
sys.exit(0)
34+
2335
run_python(
2436
["-m", "pip", "install", "-U", "pip"],
2537
warning_as_error=False,

testkitbackend/_async/requests.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@
4545
)
4646
from .._warning_check import warnings_check
4747
from ..exceptions import MarkdAsDriverError
48+
from ..test_config import (
49+
FEATURES,
50+
SKIPPED_TESTS,
51+
)
4852

4953

5054
if t.TYPE_CHECKING:
@@ -108,9 +112,6 @@ def load_config():
108112
return skips, features
109113

110114

111-
SKIPPED_TESTS, FEATURES = load_config()
112-
113-
114115
def _get_skip_reason(test_name):
115116
for skip_pattern, reason in SKIPPED_TESTS.items():
116117
if skip_pattern[0] == skip_pattern[-1] == "'":

testkitbackend/_sync/requests.py

Lines changed: 4 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

testkitbackend/exceptions.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,27 @@
1414
# limitations under the License.
1515

1616

17+
from .time_warp_compat import VERSION
18+
19+
1720
class MarkdAsDriverError(Exception):
1821
"""Wrap any error as DriverException."""
1922

2023
def __init__(self, wrapped_exc):
2124
super().__init__()
2225
self.wrapped_exc = wrapped_exc
26+
27+
28+
class TimeWarpError(Exception):
29+
"""
30+
Request cannot be fulfilled with in the current time warp mode.
31+
32+
The backend understood the request, but is running in time warp mode
33+
against an older driver that does not support the requested feature.
34+
"""
35+
36+
def __init__(self, feature_name: str):
37+
super().__init__(
38+
f"{feature_name.capitalize()} is not supported in time warp mode "
39+
f"(driver version {'.'.join(map(str, VERSION))})."
40+
)

testkitbackend/test_config.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
"Feature:Bolt:5.2": true,
5757
"Feature:Bolt:5.3": true,
5858
"Feature:Bolt:5.4": true,
59-
"Feature:Bolt:5.5": true,
59+
"Feature:Bolt:5.5": "Version was never released in a server",
6060
"Feature:Bolt:5.6": true,
6161
"Feature:Bolt:5.7": true,
6262
"Feature:Bolt:5.8": true,

testkitbackend/test_config.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Copyright (c) "Neo4j"
2+
# Neo4j Sweden AB [https://neo4j.com]
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# https://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
17+
import json
18+
import ssl
19+
from os import path
20+
21+
from .time_warp_compat import (
22+
BLOCKED_TESTKIT_FEATURES,
23+
EXTRA_TESTKIT_FEATURES,
24+
)
25+
26+
27+
__all__ = ["FEATURES", "SKIPPED_TESTS"]
28+
29+
30+
def _load_config():
31+
config_path = path.join(path.dirname(__file__), "test_config.json")
32+
with open(config_path, encoding="utf-8") as fd:
33+
config = json.load(fd)
34+
skips = config["skips"]
35+
features = [
36+
k
37+
for k, v in config["features"].items()
38+
if v is True and k not in BLOCKED_TESTKIT_FEATURES
39+
]
40+
features.extend(EXTRA_TESTKIT_FEATURES)
41+
if ssl.HAS_TLSv1_3:
42+
features += ["Feature:TLS:1.3"]
43+
return skips, features
44+
45+
46+
SKIPPED_TESTS, FEATURES = _load_config()

0 commit comments

Comments
 (0)