Skip to content

Commit db1b258

Browse files
committed
WL#15353: add support for running tests in a container
In order to run the automated test suite, and besides a running MySQL server instance, users need to have a previously installed compatible Node.js engine version and, additionally, need to install the required 3rd-party dependencies. Although very little, this process always requires a bit of Node.js expertise, and can be a hurdle for developers that want to test specific server features, and not the corresponding client/connector UX. One way to introduce a small shortcut and reduce the burden of setting up a local testing environment is by leveraging docker containers. In this case, users would only need to install the container engine, and any additional setup would be performed automatically and without requiring any specific language/platform knowledge apart from knowing to execute a shell script in the system and launching the MySQL server. This patch introduces tooling that facilitates the task of running the test suite using a docker container and a running MySQL server instance on Unix-based environments (such as Linux and macOS). It delivers a shell script that automates the task of building the container image and run it using the exact same configuration parameters that can be specified whilst in the local system environment. At the same time, it removes some older tooling used to facilitate a similar task which was not in any way tied to the existing public npm scripts and was, at best, a source of confusion. Change-Id: I2a5fdaf8edb15fd6be5f70d7457a293fe7d1d6e3
1 parent 3b02a13 commit db1b258

File tree

5 files changed

+188
-57
lines changed

5 files changed

+188
-57
lines changed

CONTRIBUTING.md

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,11 @@ $ npm run test:functional
6060
If the server is not running on the same machine, is available only via a local UNIX socket, or if it is initialized using other custom configuration details, those can be provided to the test runner using the following environment variables:
6161

6262
* `MYSQLX_HOST` (`'localhost'` by default)
63+
* `MYSQLX_DEFAULT_SCHEMA` (`'nodejsmysqlxtest'` by default)
6364
* `MYSQLX_PASSWORD` (empty by default)
6465
* `MYSQLX_PORT` (`33060` by default)
6566
* `MYSQLX_SOCKET` (`undefined` by default)
66-
* `MYSQLX_DEFAULT_SCHEMA` (`'nodejsmysqlxtest'` by default)
67+
* `MYSQLX_USER` (`root` by default)
6768

6869
For example:
6970

@@ -80,6 +81,37 @@ $ npm run test
8081
$ npm run test:unit && npm run test:functional
8182
```
8283

84+
#### Using a Docker container
85+
86+
Alternatively, for Linux or macOS users, there is a script that builds and runs a Docker container which then executes the test suite. This means no external dependency, apart from a running MySQL server, is needed.
87+
88+
The script uses the environment variables described previously and introduces a few new ones. These are mostly meant to be used for configuring the Docker container itself. They allow to specify the path to a Node.js engine image, the network proxy setup and the URL of the NPM registry to use.
89+
90+
* `BASE_IMAGE` (`container-registry.oracle.com/graalvm/nodejs:latest` by default)
91+
* `HTTP_PROXY` (value of the environment variable in the host by default)
92+
* `HTTPS_PROXY` (value of the environment variable in the host by default)
93+
* `NO_PROXY` (value of the environment variable in the host by default)
94+
* `NPM_REGISTRY` (`https://registry.npmjs.org/` by default)
95+
96+
There is one additional environment variable called `TEST_PATTERN` which can be used to provide a string or a regular expression that is applied for filtering one or more matching tests to execute.
97+
98+
Ultimately, the script allows an argument which identifies the underlying NPM script that gets executed. So, in theory, any of the available NPM scripts can be executed in the container, but by default, it will execute the `test` script.
99+
100+
```sh
101+
# executing the default test script with the default environment (Linux only)
102+
$ ./test/docker/run.sh
103+
# executing the unit test suite
104+
$ ./test/docker/run.sh test:unit
105+
# executing all TCP-based functional tests whose description matches the given pattern
106+
$ MYSQLX_HOST='<hostname_or_IP_address>' TEST_PATTERN='using CRUD' ./test/docker/run.sh test:functional
107+
# executing all functional tests (Linux only)
108+
$ MYSQLX_SOCKET='/path/to/socket' ./test/docker/run.sh test:functional
109+
```
110+
111+
Similar to when the tests run on a local environment, the `MYSQLX_HOST` variable is only relevant for the functional tests. On Linux, the variable is optional and the Docker container will run using the "host" network mode whilst tests assume the MySQL server is listening on `localhost`. On macOS, since containers run on a virtual machine, host loopback addresses are not reachable. In that case, the `MYSQLX_HOST` variable is required and should specify the hostname or IP address of the MySQL server.
112+
113+
Due to some [know limitations](https://github.com/docker/for-mac/issues/483) on the macOS Docker architecture, Unix socket tests can only run on Linux. In that case, if the `MYSQLX_SOCKET` variable is explicitely specified, a shared volume between the host and the container will be created as a mount point from the socket file path in the host and an internal container directory specified as a volume, where the socket file path becomes available.
114+
83115
### Test Coverage
84116

85117
When submitting a patch that introduces changes to the source code, you need to make sure that those changes are be accompanied by a proper set of tests that cover 100% of the affected code paths. This is easily auditable by generating proper test coverage HTML and stdout reports using the following command:

bin/wait-for.js

Lines changed: 0 additions & 54 deletions
This file was deleted.

package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,8 @@
5656
"lint": "npm run lint:lib && npm run lint:types",
5757
"mocha": "mocha --reporter spec --timeout 10000 --recursive",
5858
"prepack": "node bin/prepack.js",
59-
"pretest": "node bin/wait-for.js",
6059
"test": "tsd && npm run mocha test/unit test/functional/default",
61-
"test:functional": "npm run pretest && npm run mocha test/functional/default",
60+
"test:functional": "npm run mocha test/functional/default",
6261
"test:unit": "npm run mocha test/unit",
6362
"test:types": "tsd"
6463
},

test/docker/Dockerfile

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# Copyright (c) 2022, Oracle and/or its affiliates.
2+
#
3+
# This program is free software; you can redistribute it and/or modify
4+
# it under the terms of the GNU General Public License, version 2.0, as
5+
# published by the Free Software Foundation.
6+
#
7+
# This program is also distributed with certain software (including
8+
# but not limited to OpenSSL) that is licensed under separate terms,
9+
# as designated in a particular file or component or in included license
10+
# documentation. The authors of MySQL hereby grant you an
11+
# additional permission to link the program and your derivative works
12+
# with the separately licensed software that they have included with
13+
# MySQL.
14+
#
15+
# Without limiting anything contained in the foregoing, this file,
16+
# which is part of MySQL Connector/Node.js, is also subject to the
17+
# Universal FOSS Exception, version 1.0, a copy of which can be found at
18+
# http://oss.oracle.com/licenses/universal-foss-exception.
19+
#
20+
# This program is distributed in the hope that it will be useful, but
21+
# WITHOUT ANY WARRANTY; without even the implied warranty of
22+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
23+
# See the GNU General Public License, version 2.0, for more details.
24+
#
25+
# You should have received a copy of the GNU General Public License
26+
# along with this program; if not, write to the Free Software Foundation, Inc.,
27+
# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28+
29+
# By default, the container will use the latest GraalVM Node.js image
30+
# from OCR. The BASE_IMAGE environment variable can be used to pull
31+
# any other Node.js image from any other Docker registry.
32+
ARG BASE_IMAGE=container-registry.oracle.com/graalvm/nodejs:latest
33+
FROM ${BASE_IMAGE}
34+
35+
# In order to be able to run the tests within a private network, optional
36+
# proxy configurations can be used.
37+
ARG HTTP_PROXY
38+
ARG HTTPS_PROXY
39+
ARG NO_PROXY
40+
ENV HTTP_PROXY=${HTTP_PROXY} HTTPS_PROXY=${HTTPS_PROXY} NO_PROXY=${NO_PROXY}
41+
42+
WORKDIR /mysql-connector-nodejs
43+
44+
# The package.json file needs to exist before the 3rd-party dependencies
45+
# are installed.
46+
COPY package.json .
47+
48+
# It is possible to use a private NPM registry.
49+
ARG NPM_REGISTRY=https://registry.npmjs.org/
50+
RUN npm config set registry ${NPM_REGISTRY}
51+
RUN npm install --quiet
52+
53+
# This volume can be used to share, among other things, the Unix socket file
54+
# with the container.
55+
VOLUME [ "/shared" ]
56+
57+
# Artifacts are copied according to how much they might change in the future
58+
# to leverage layer caching.
59+
COPY .eslintrc.js .
60+
COPY bin bin
61+
COPY index.js .
62+
COPY types types
63+
COPY test test
64+
COPY lib lib

test/docker/run.sh

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
# Copyright (c) 2022, Oracle and/or its affiliates.
2+
#
3+
# This program is free software; you can redistribute it and/or modify
4+
# it under the terms of the GNU General Public License, version 2.0, as
5+
# published by the Free Software Foundation.
6+
#
7+
# This program is also distributed with certain software (including
8+
# but not limited to OpenSSL) that is licensed under separate terms,
9+
# as designated in a particular file or component or in included license
10+
# documentation. The authors of MySQL hereby grant you an
11+
# additional permission to link the program and your derivative works
12+
# with the separately licensed software that they have included with
13+
# MySQL.
14+
#
15+
# Without limiting anything contained in the foregoing, this file,
16+
# which is part of MySQL Connector/Node.js, is also subject to the
17+
# Universal FOSS Exception, version 1.0, a copy of which can be found at
18+
# http://oss.oracle.com/licenses/universal-foss-exception.
19+
#
20+
# This program is distributed in the hope that it will be useful, but
21+
# WITHOUT ANY WARRANTY; without even the implied warranty of
22+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
23+
# See the GNU General Public License, version 2.0, for more details.
24+
#
25+
# You should have received a copy of the GNU General Public License
26+
# along with this program; if not, write to the Free Software Foundation, Inc.,
27+
# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28+
29+
#!/bin/sh
30+
31+
image=mysql-connector-nodejs
32+
version=${MYSQL_VERSION:-latest}
33+
input_test_script=$1
34+
test_script=${input_test_script:-test}
35+
basedir=$(dirname $0)
36+
37+
# The BASE_IMAGE, HTTPS_PROXY, HTTP_PROXY, NO_PROXY and NPM_REGISTRY
38+
# environment variables are used as build arguments. Unless they are
39+
# explicitly specified, the script will use their system-wide values.
40+
# It should be possible to run script from anywhere in the file system. So,
41+
# the absolute Dockerfile and context paths should be specified.
42+
docker build \
43+
--build-arg BASE_IMAGE \
44+
--build-arg HTTP_PROXY \
45+
--build-arg HTTPS_PROXY \
46+
--build-arg NO_PROXY \
47+
--build-arg NPM_REGISTRY \
48+
--tag $image:$version \
49+
--file $basedir/Dockerfile \
50+
$basedir/../../
51+
52+
# If MYSQLX_HOST is empty, "localhost" should be used by default.
53+
# The variable needs to be re-assigned in order to determine if it contains a
54+
# loopback address (implicitly or explicitly).
55+
if [ -z "$MYSQLX_HOST" ]
56+
then
57+
MYSQLX_HOST="localhost"
58+
fi
59+
60+
# If MYSQLX_HOST is a loopback address, a new flag is created. This flag
61+
# allows to determine the network mode in which the Docker container will
62+
# run. The container should run in "host" mode if MYSQLX_HOST is a loopback
63+
# address and should run in "bridge" mode (default) if MYSQLX_HOST is
64+
# a different host name or IP address.
65+
if [ "$MYSQLX_HOST" == "localhost" ] || [ "$MYSQLX_HOST" == "127.0.0.1" ]
66+
then
67+
MYSQL_LOCALHOST=$MYSQLX_HOST
68+
fi
69+
70+
# If MYSQLX_SOCKET is not empty, the corresponding path to the Unix socket
71+
# file should be shared with the container using a Docker volume.
72+
# Additionally, the variable should be assigned the appropriate absolute
73+
# file path from the container standpoint.
74+
# If MYSQL_LOCALHOST is not empty, the container should run using the "host"
75+
# network mode. If it is empty, the container should run using the "bridge"
76+
# network mode, which is what happens by default.
77+
docker run \
78+
--rm \
79+
--interactive \
80+
--tty \
81+
${MYSQL_LOCALHOST:+ --network host} \
82+
${MYSQLX_SOCKET:+ --volume $MYSQLX_SOCKET:/shared/mysqlx.sock} \
83+
--env MYSQLX_HOST \
84+
--env MYSQLX_PASSWORD \
85+
--env MYSQLX_PORT \
86+
${MYSQLX_SOCKET:+ --env MYSQLX_SOCKET=/shared/mysqlx.sock} \
87+
--env MYSQLX_USER \
88+
--env TEST_PATTERN \
89+
$image:$version \
90+
npm run $test_script -- -- --grep "$TEST_PATTERN"

0 commit comments

Comments
 (0)