Skip to content

Commit

Permalink
Docker-based test servers for network-related Qt autotests on Windows
Browse files Browse the repository at this point in the history
There is no docker bridge on Windows. Docker document recommends using
port mapping to connect to a container. The problem is that it causes a
port conflict if the user is running a service that binds the same port
on the host. This change applies the same solution of macOS to deploy
the docker environment into VirtualBox and use the host network option.

Task-number: QTQAINFRA-2294
Change-Id: Iedcb8daa39373f02adb59f02eae2775f02870c54
Reviewed-by: Jędrzej Nowacki <[email protected]>
Reviewed-by: Edward Welbourne <[email protected]>
  • Loading branch information
ryanjh committed Jan 23, 2019
1 parent 4552edd commit beab266
Show file tree
Hide file tree
Showing 9 changed files with 175 additions and 19 deletions.
79 changes: 61 additions & 18 deletions tests/auto/testserver.pri
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,12 @@ debug_and_release:!build_pass: return()

TESTSERVER_VERSION = $$system(docker-compose --version)

equals(QMAKE_HOST.os, Windows)|isEmpty(TESTSERVER_VERSION) {
isEmpty(TESTSERVER_VERSION) {
# Make check with server "qt-test-server.qt-test-net" as a fallback
message("testserver: qt-test-server.qt-test-net")
} else {
# Make check with test servers
# Make check with docker test servers
DNSDOMAIN = test-net.qt.local

equals(QMAKE_HOST.os, Darwin) {
# There is no docker bridge on macOS. It is impossible to ping a container.
# Docker docs recommends using port mapping to connect to a container;
Expand All @@ -77,44 +78,85 @@ equals(QMAKE_HOST.os, Windows)|isEmpty(TESTSERVER_VERSION) {

# The environment variables passed to the docker-compose file
TEST_ENV = 'MACHINE_IP=$(shell docker-machine ip qt-test-server)'
TEST_ENV += 'TEST_DOMAIN=$$DNSDOMAIN'
TEST_CMD = env
} else:equals(QMAKE_HOST.os, Windows) {
# There is no docker bridge on Windows. It is impossible to ping a container.
# Use docker-machine to deploy the docker environment into VirtualBox.
TESTSERVER_COMPOSE_FILE = \
$$dirname(_QMAKE_CONF_)/tests/testserver/docker-compose-for-windows.yml

# Bonjour only works within a single broadcast domain.
DNSDOMAIN = local

# The connection configuration for the target machine
MACHINE_CONFIG = (docker-machine config qt-test-server)

# The environment variables passed to the docker-compose file
TEST_ENV = '\$\$env:MACHINE_IP = docker-machine ip qt-test-server;'
TEST_ENV += '\$\$env:TEST_DOMAIN = $$shell_quote(\"$$DNSDOMAIN\");'
TEST_CMD = 'PowerShell -noprofile'
CONFIG += PowerShell
} else {
TESTSERVER_COMPOSE_FILE = $$dirname(_QMAKE_CONF_)/tests/testserver/docker-compose.yml
DEFINES += QT_TEST_SERVER_NAME
}

# The domain name is relevant to https keycert (qnetworkreply/crts/qt-test-net-cacert.pem).
DEFINES += QT_TEST_SERVER QT_TEST_SERVER_DOMAIN=$$shell_quote(\"$${DNSDOMAIN}\")

# Ensure that the docker-compose file is provided. It is a configuration
# file which is mandatory for all docker-compose commands. You can get more
# detail from the description of TESTSERVER_COMPOSE_FILE above. There is
# also an example showing how to configure it manually.
FILE_PRETEST_MSG = "Project variable 'TESTSERVER_COMPOSE_FILE' is not set"
testserver_pretest.commands = $(info "testserver:" $$TESTSERVER_VERSION)
testserver_pretest.commands += $(if $$TESTSERVER_COMPOSE_FILE,,$(error $$FILE_PRETEST_MSG))
PowerShell {
testserver_pretest.commands = echo $$TESTSERVER_VERSION &&
testserver_pretest.commands += \
$$TEST_CMD if ([String]::IsNullOrEmpty($$shell_quote(\"$$TESTSERVER_COMPOSE_FILE\"))) \
{Write-Error $$shell_quote(\"$$FILE_PRETEST_MSG\")} &&
} else {
testserver_pretest.commands = $(info "testserver:" $$TESTSERVER_VERSION)
testserver_pretest.commands += $(if $$TESTSERVER_COMPOSE_FILE,,$(error $$FILE_PRETEST_MSG))
}

# Make sure docker-machine is both created and running. The docker_machine
# script is used to deploy the docker environment into VirtualBox.
# Example: qt5/coin/provisioning/common/shared/testserver/docker_machine.sh
!isEmpty(MACHINE_CONFIG) {
MACHINE_LIST_CMD = docker-machine ls -q --filter "Name=^qt-test-server$"
MACHINE_LIST_CMD = docker-machine ls -q --filter "Name=^qt-test-server\$\$"
MACHINE_LIST_MSG = "Docker machine qt-test-server not found"
testserver_pretest.commands += \
$(if $(shell $$MACHINE_LIST_CMD),,$(error $$MACHINE_LIST_MSG))
PowerShell {
testserver_pretest.commands += $$TEST_CMD if (!($$MACHINE_LIST_CMD)) \
{Write-Error $$shell_quote(\"$$MACHINE_LIST_MSG\")} &&
} else {
testserver_pretest.commands += \
$(if $(shell $$MACHINE_LIST_CMD),,$(error $$MACHINE_LIST_MSG))
}

MACHINE_STATE_CMD = \
docker-machine ls -q --filter "State=Running" --filter "Name=^qt-test-server$"
docker-machine ls -q --filter "State=Running" --filter "Name=^qt-test-server\$\$"
MACHINE_START_CMD = docker-machine start qt-test-server
testserver_pretest.commands += \
$(if $(shell $$MACHINE_STATE_CMD),,$(shell $$MACHINE_START_CMD > /dev/null))
PowerShell {
testserver_pretest.commands += \
$$TEST_CMD if (!($$MACHINE_STATE_CMD)) {$$MACHINE_START_CMD} &&
} else {
testserver_pretest.commands += \
$(if $(shell $$MACHINE_STATE_CMD),,$(shell $$MACHINE_START_CMD > /dev/null))
}
}

# Before starting the test servers, it requires the user to run the setup
# script (coin/provisioning/.../testserver/docker_testserver.sh) in advance.
IMAGE_PRETEST_CMD = docker $$MACHINE_CONFIG images -aq "qt-test-server-*"
IMAGE_PRETEST_MSG = "Docker image qt-test-server-* not found"
testserver_pretest.commands += $(if $(shell $$IMAGE_PRETEST_CMD),,$(error $$IMAGE_PRETEST_MSG))

# The domain name is relevant to https keycert (qnetworkreply/crts/qt-test-net-cacert.pem).
DNSDOMAIN = test-net.qt.local
DEFINES += QT_TEST_SERVER QT_TEST_SERVER_DOMAIN=$$shell_quote(\"$${DNSDOMAIN}\")
PowerShell {
testserver_pretest.commands += $$TEST_CMD if (!($$IMAGE_PRETEST_CMD)) \
{Write-Error $$shell_quote(\"$$IMAGE_PRETEST_MSG\")}
} else {
testserver_pretest.commands += \
$(if $(shell $$IMAGE_PRETEST_CMD),,$(error $$IMAGE_PRETEST_MSG))
}

# Rename the check target of testcase feature
check.target = check_network
Expand All @@ -124,14 +166,15 @@ equals(QMAKE_HOST.os, Windows)|isEmpty(TESTSERVER_VERSION) {
testserver_test.depends = testserver_pretest

# Bring up test servers and make sure the services are ready.
!isEmpty(TEST_ENV): testserver_test.commands = env $$TEST_ENV
!isEmpty(TEST_CMD): testserver_test.commands = $$TEST_CMD $$TEST_ENV
testserver_test.commands += docker-compose $$MACHINE_CONFIG -f $$TESTSERVER_COMPOSE_FILE up \
--detach --force-recreate --timeout 1 $${QT_TEST_SERVER_LIST} &&

# Check test cases with docker-based test servers.
testserver_test.commands += $(MAKE) -f $(MAKEFILE) check_network;
testserver_test.commands += $(MAKE) -f $(MAKEFILE) check_network &&

# Stop and remove test servers after testing.
!isEmpty(TEST_CMD): testserver_test.commands += $$TEST_CMD $$TEST_ENV
testserver_test.commands += docker-compose $$MACHINE_CONFIG -f $$TESTSERVER_COMPOSE_FILE down \
--timeout 1

Expand Down
2 changes: 2 additions & 0 deletions tests/testserver/apache2/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
* text eol=lf
*.gif -text
2 changes: 2 additions & 0 deletions tests/testserver/common/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.sh text eol=lf
*.conf text eol=lf
4 changes: 3 additions & 1 deletion tests/testserver/common/startup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ do $RUN_CMD
done

# start multicast DNS service discovery (mDNS)
sed -i "s,#domain-name=local,domain-name=test-net.qt.local," /etc/avahi/avahi-daemon.conf
sed -i -e "s,#domain-name=local,domain-name=${test_domain:-test-net.qt.local}," \
-e "s,#publish-aaaa-on-ipv4=yes,publish-aaaa-on-ipv4=no," \
/etc/avahi/avahi-daemon.conf
service dbus restart
service avahi-daemon restart

Expand Down
2 changes: 2 additions & 0 deletions tests/testserver/danted/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.sh text eol=lf
*.conf text eol=lf
99 changes: 99 additions & 0 deletions tests/testserver/docker-compose-for-windows.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
version: '3.4'

# The tag of images is used by docker compose file to launch the corresponding
# docker containers. The value of tag comes from the provisioning script
# (coin/provisioning/.../testserver/docker_testserver.sh). The script gets SHA-1
# of each server context as the tag of docker images. If one of the server
# contexts gets changes, please make sure to update this compose file as well.
# You can run command 'docker images' to list all the tags of test server images.
# For example:
# REPOSITORY TAG
# qt-test-server-apache2 537fe302f61851d1663f41495230d8e3554a4a13

services:
apache2:
image: qt-test-server-apache2:537fe302f61851d1663f41495230d8e3554a4a13
container_name: qt-test-server-apache2
domainname: ${TEST_DOMAIN}
volumes:
- ./common:/common:ro
- ./apache2:/service:ro
entrypoint: common/startup.sh
command: [common/ssl.sh, service/apache2.sh]
network_mode: "host"
extra_hosts:
- "qt-test-server.${TEST_DOMAIN}:${MACHINE_IP}"
environment:
- test_domain=${TEST_DOMAIN}

squid:
image: qt-test-server-squid:9c32f41b19aca3d778733c4d8fb0ecc5955e893c
container_name: qt-test-server-squid
domainname: ${TEST_DOMAIN}
depends_on:
- apache2
volumes:
- ./common:/common:ro
- ./squid:/service:ro
entrypoint: common/startup.sh
command: service/squid.sh
network_mode: "host"
extra_hosts:
- "qt-test-server.${TEST_DOMAIN}:${MACHINE_IP}"
environment:
- test_domain=${TEST_DOMAIN}

vsftpd:
image: qt-test-server-vsftpd:f3a9c8d793a77cc007c0e4e481bec01f9e3eeb7e
container_name: qt-test-server-vsftpd
domainname: ${TEST_DOMAIN}
volumes:
- ./common:/common:ro
- ./vsftpd:/service:ro
entrypoint: common/startup.sh
command: service/vsftpd.sh
network_mode: "host"
extra_hosts:
- "qt-test-server.${TEST_DOMAIN}:${MACHINE_IP}"
environment:
- test_domain=${TEST_DOMAIN}

ftp-proxy:
image: qt-test-server-ftp-proxy:d7de8b28392d173db512a558ccc84ead8bece2ae
container_name: qt-test-server-ftp-proxy
domainname: ${TEST_DOMAIN}
depends_on:
- vsftpd
volumes:
- ./common:/common:ro
- ./ftp-proxy:/service:ro
entrypoint: common/startup.sh
command: service/ftp-proxy.sh
network_mode: "host"
extra_hosts:
- "qt-test-server.${TEST_DOMAIN}:${MACHINE_IP}"
environment:
- test_domain=${TEST_DOMAIN}

danted:
image: qt-test-server-danted:35607f9b790524cf9690c7d12a9a401696b7b6b5
container_name: qt-test-server-danted
domainname: ${TEST_DOMAIN}
depends_on:
- apache2
- vsftpd
- ftp-proxy
volumes:
- ./common:/common:ro
- ./danted:/service:ro
entrypoint: common/startup.sh
command: service/danted.sh
network_mode: "host"
extra_hosts:
- "qt-test-server.${TEST_DOMAIN}:${MACHINE_IP}"
environment:
- danted_internal=${MACHINE_IP:-eth0}
- danted_external=${MACHINE_IP:-eth0}
- danted_auth_internal=${MACHINE_IP:-eth0}
- danted_auth_external=${MACHINE_IP:-eth0}
- test_domain=${TEST_DOMAIN}
2 changes: 2 additions & 0 deletions tests/testserver/ftp-proxy/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.sh text eol=lf
*.conf text eol=lf
2 changes: 2 additions & 0 deletions tests/testserver/squid/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.sh text eol=lf
*.conf text eol=lf
2 changes: 2 additions & 0 deletions tests/testserver/vsftpd/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
* text eol=lf
*.gif -text

0 comments on commit beab266

Please sign in to comment.