From 4485b04be9af47e3c6beed47ce4277c23bd3edea Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Wed, 1 Jun 2016 12:25:14 +0800 Subject: [PATCH 01/16] tests: Add utilities for docker testing docker.py is added with a number of useful subcommands to manager docker images and instances for QEMU docker testing. Subcommands are: run: A wrapper of "docker run" (or "sudo -n docker run" if necessary), which takes care of killing and removing the running container at SIGINT. clean: Tear down all the containers including inactive ones that are started by docker_run. build: Compare an image from given dockerfile and rebuild it if they're different. Signed-off-by: Fam Zheng Message-id: 1464755128-32490-2-git-send-email-famz@redhat.com --- tests/docker/docker.py | 194 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100755 tests/docker/docker.py diff --git a/tests/docker/docker.py b/tests/docker/docker.py new file mode 100755 index 0000000000..0151362d17 --- /dev/null +++ b/tests/docker/docker.py @@ -0,0 +1,194 @@ +#!/usr/bin/env python2 +# +# Docker controlling module +# +# Copyright (c) 2016 Red Hat Inc. +# +# Authors: +# Fam Zheng +# +# This work is licensed under the terms of the GNU GPL, version 2 +# or (at your option) any later version. See the COPYING file in +# the top-level directory. + +import os +import sys +import subprocess +import json +import hashlib +import atexit +import uuid +import argparse +import tempfile +from shutil import copy + +def _text_checksum(text): + """Calculate a digest string unique to the text content""" + return hashlib.sha1(text).hexdigest() + +def _guess_docker_command(): + """ Guess a working docker command or raise exception if not found""" + commands = [["docker"], ["sudo", "-n", "docker"]] + for cmd in commands: + if subprocess.call(cmd + ["images"], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) == 0: + return cmd + commands_txt = "\n".join([" " + " ".join(x) for x in commands]) + raise Exception("Cannot find working docker command. Tried:\n%s" % \ + commands_txt) + +class Docker(object): + """ Running Docker commands """ + def __init__(self): + self._command = _guess_docker_command() + self._instances = [] + atexit.register(self._kill_instances) + + def _do(self, cmd, quiet=True, **kwargs): + if quiet: + kwargs["stdout"] = subprocess.PIPE + return subprocess.call(self._command + cmd, **kwargs) + + def _do_kill_instances(self, only_known, only_active=True): + cmd = ["ps", "-q"] + if not only_active: + cmd.append("-a") + for i in self._output(cmd).split(): + resp = self._output(["inspect", i]) + labels = json.loads(resp)[0]["Config"]["Labels"] + active = json.loads(resp)[0]["State"]["Running"] + if not labels: + continue + instance_uuid = labels.get("com.qemu.instance.uuid", None) + if not instance_uuid: + continue + if only_known and instance_uuid not in self._instances: + continue + print "Terminating", i + if active: + self._do(["kill", i]) + self._do(["rm", i]) + + def clean(self): + self._do_kill_instances(False, False) + return 0 + + def _kill_instances(self): + return self._do_kill_instances(True) + + def _output(self, cmd, **kwargs): + return subprocess.check_output(self._command + cmd, + stderr=subprocess.STDOUT, + **kwargs) + + def get_image_dockerfile_checksum(self, tag): + resp = self._output(["inspect", tag]) + labels = json.loads(resp)[0]["Config"].get("Labels", {}) + return labels.get("com.qemu.dockerfile-checksum", "") + + def build_image(self, tag, dockerfile, df_path, quiet=True, argv=None): + if argv == None: + argv = [] + tmp_dir = tempfile.mkdtemp(prefix="docker_build") + + tmp_df = tempfile.NamedTemporaryFile(dir=tmp_dir, suffix=".docker") + tmp_df.write(dockerfile) + + tmp_df.write("\n") + tmp_df.write("LABEL com.qemu.dockerfile-checksum=%s" % + _text_checksum(dockerfile)) + tmp_df.flush() + self._do(["build", "-t", tag, "-f", tmp_df.name] + argv + \ + [tmp_dir], + quiet=quiet) + + def image_matches_dockerfile(self, tag, dockerfile): + try: + checksum = self.get_image_dockerfile_checksum(tag) + except Exception: + return False + return checksum == _text_checksum(dockerfile) + + def run(self, cmd, keep, quiet): + label = uuid.uuid1().hex + if not keep: + self._instances.append(label) + ret = self._do(["run", "--label", + "com.qemu.instance.uuid=" + label] + cmd, + quiet=quiet) + if not keep: + self._instances.remove(label) + return ret + +class SubCommand(object): + """A SubCommand template base class""" + name = None # Subcommand name + def shared_args(self, parser): + parser.add_argument("--quiet", action="store_true", + help="Run quietly unless an error occured") + + def args(self, parser): + """Setup argument parser""" + pass + def run(self, args, argv): + """Run command. + args: parsed argument by argument parser. + argv: remaining arguments from sys.argv. + """ + pass + +class RunCommand(SubCommand): + """Invoke docker run and take care of cleaning up""" + name = "run" + def args(self, parser): + parser.add_argument("--keep", action="store_true", + help="Don't remove image when command completes") + def run(self, args, argv): + return Docker().run(argv, args.keep, quiet=args.quiet) + +class BuildCommand(SubCommand): + """ Build docker image out of a dockerfile. Arguments: """ + name = "build" + def args(self, parser): + parser.add_argument("tag", + help="Image Tag") + parser.add_argument("dockerfile", + help="Dockerfile name") + + def run(self, args, argv): + dockerfile = open(args.dockerfile, "rb").read() + tag = args.tag + + dkr = Docker() + if dkr.image_matches_dockerfile(tag, dockerfile): + if not args.quiet: + print "Image is up to date." + return 0 + + dkr.build_image(tag, dockerfile, args.dockerfile, + quiet=args.quiet, argv=argv) + return 0 + +class CleanCommand(SubCommand): + """Clean up docker instances""" + name = "clean" + def run(self, args, argv): + Docker().clean() + return 0 + +def main(): + parser = argparse.ArgumentParser(description="A Docker helper", + usage="%s ..." % os.path.basename(sys.argv[0])) + subparsers = parser.add_subparsers(title="subcommands", help=None) + for cls in SubCommand.__subclasses__(): + cmd = cls() + subp = subparsers.add_parser(cmd.name, help=cmd.__doc__) + cmd.shared_args(subp) + cmd.args(subp) + subp.set_defaults(cmdobj=cmd) + args, argv = parser.parse_known_args() + return args.cmdobj.run(args, argv) + +if __name__ == "__main__": + sys.exit(main()) From 2f4e4dc237261c76734d8ae1d8e09d2983d2f1ca Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Wed, 1 Jun 2016 12:25:15 +0800 Subject: [PATCH 02/16] rules.mak: Add "COMMA" constant Using "," literal in $(call quiet-command, ...) arguments is awkward. Add this constant to make it at least doable. Signed-off-by: Fam Zheng Message-id: 1464755128-32490-3-git-send-email-famz@redhat.com --- rules.mak | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rules.mak b/rules.mak index d1ff311254..4a8f464940 100644 --- a/rules.mak +++ b/rules.mak @@ -1,4 +1,6 @@ +COMMA := , + # Don't use implicit rules or variables # we have explicit rules for everything MAKEFLAGS += -rR From fb57c881022ebbf4ad5fdb688360985d11521b4a Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Wed, 1 Jun 2016 12:25:16 +0800 Subject: [PATCH 03/16] Makefile: Always include rules.mak When config-host.mak is not found it is safe to assume SRC_PATH is ".". So, it is okay to move inclusion of ruls.mak out of the ifeq condition. Signed-off-by: Fam Zheng Message-id: 1464755128-32490-4-git-send-email-famz@redhat.com --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 3a3c5dc647..1c2a7bde13 100644 --- a/Makefile +++ b/Makefile @@ -30,7 +30,6 @@ CONFIG_ALL=y -include config-all-devices.mak -include config-all-disas.mak -include $(SRC_PATH)/rules.mak config-host.mak: $(SRC_PATH)/configure @echo $@ is out-of-date, running configure @# TODO: The next lines include code which supports a smooth @@ -49,6 +48,8 @@ ifneq ($(filter-out $(UNCHECKED_GOALS),$(MAKECMDGOALS)),$(if $(MAKECMDGOALS),,fa endif endif +include $(SRC_PATH)/rules.mak + GENERATED_HEADERS = config-host.h qemu-options.def GENERATED_HEADERS += qmp-commands.h qapi-types.h qapi-visit.h qapi-event.h GENERATED_SOURCES += qmp-marshal.c qapi-types.c qapi-visit.c qapi-event.c From 324027c24cd02d8333c0035de3d69b025fb1030f Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Wed, 1 Jun 2016 12:25:17 +0800 Subject: [PATCH 04/16] Makefile: Rules for docker testing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds a group of make targets to run docker tests, all are available in source tree without running ./configure. The usage is shown with "make docker". Besides the fixed ones, dynamic targets for building each image and running each test in each image are generated automatically by make, scanning $(SRC_PATH)/tests/docker/ files with specific patterns. Alternative to manually list particular targets (docker-TEST@IMAGE) set, you can control which tests/images to run by filtering variables, TESTS= and IMAGES=, which are expressed in Makefile pattern syntax, "foo% %bar ...". For example: $ make docker-test IMAGES="ubuntu fedora" Unfortunately, it's impossible to propagate "-j $JOBS" into make in containers, however since each combination is made a first class target in the top Makefile, "make -j$N docker-test" still parallels the tests coarsely. Still, $J is made a magic variable to let all make invocations in containers to use -j$J. Instead of providing a live version of the source tree to the docker container we snapshot it with git-archive. This ensures the tree is in a pristine state for whatever operations the container is going to run on them. Uncommitted changes known to files known by the git index will be included in the snapshot if there are any. Signed-off-by: Fam Zheng Signed-off-by: Alex Bennée Message-id: 1464755128-32490-5-git-send-email-famz@redhat.com --- Makefile | 4 +- tests/docker/Makefile.include | 123 ++++++++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 tests/docker/Makefile.include diff --git a/Makefile b/Makefile index 1c2a7bde13..b8563db686 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ BUILD_DIR=$(CURDIR) # Before including a proper config-host.mak, assume we are in the source tree SRC_PATH=. -UNCHECKED_GOALS := %clean TAGS cscope ctags +UNCHECKED_GOALS := %clean TAGS cscope ctags docker docker-% # All following code might depend on configuration variables ifneq ($(wildcard config-host.mak),) @@ -644,3 +644,5 @@ endif # Include automatically generated dependency files # Dependencies in Makefile.objs files come from our recursive subdir rules -include $(wildcard *.d tests/*.d) + +include $(SRC_PATH)/tests/docker/Makefile.include diff --git a/tests/docker/Makefile.include b/tests/docker/Makefile.include new file mode 100644 index 0000000000..ef8bcaea59 --- /dev/null +++ b/tests/docker/Makefile.include @@ -0,0 +1,123 @@ +# Makefile for Docker tests + +.PHONY: docker docker-test docker-clean docker-image docker-qemu-src + +DOCKER_SUFFIX := .docker +DOCKER_FILES_DIR := $(SRC_PATH)/tests/docker/dockerfiles +DOCKER_IMAGES := $(notdir $(basename $(wildcard $(DOCKER_FILES_DIR)/*.docker))) +DOCKER_TARGETS := $(patsubst %,docker-image-%,$(DOCKER_IMAGES)) +# Use a global constant ccache directory to speed up repetitive builds +DOCKER_CCACHE_DIR := $$HOME/.cache/qemu-docker-ccache + +DOCKER_TESTS := $(notdir $(shell \ + find $(SRC_PATH)/tests/docker/ -name 'test-*' -type f)) + +DOCKER_TOOLS := travis + +TESTS ?= % +IMAGES ?= % + +# Make archive from git repo $1 to tar.gz $2 +make-archive-maybe = $(if $(wildcard $1/*), \ + $(call quiet-command, \ + (cd $1; if git diff-index --quiet HEAD -- &>/dev/null; then \ + git archive -1 HEAD --format=tar.gz -o $2; \ + else \ + git archive -1 $$(git stash create) --format=tar.gz -o $2; \ + fi), \ + " ARCHIVE $(notdir $2)")) + +CUR_TIME := $(shell date +%Y-%m-%d-%H.%M.%S.$$$$) +# Makes the definition constant after the first expansion +DOCKER_SRC_COPY = $(eval DOCKER_SRC_COPY := docker-src.$(CUR_TIME))$(DOCKER_SRC_COPY) + +$(DOCKER_SRC_COPY): + @mkdir $@ + $(call make-archive-maybe, $(SRC_PATH), $@/qemu.tgz) + $(call make-archive-maybe, $(SRC_PATH)/dtc, $@/dtc.tgz) + $(call make-archive-maybe, $(SRC_PATH)/pixman, $@/pixman.tgz) + $(call quiet-command, cp $(SRC_PATH)/tests/docker/run $@/run, \ + " COPY RUNNER") + +docker-qemu-src: $(DOCKER_SRC_COPY) + +docker-image: ${DOCKER_TARGETS} + +# General rule for building docker images +docker-image-%: $(DOCKER_FILES_DIR)/%.docker + $(call quiet-command,\ + $(SRC_PATH)/tests/docker/docker.py build qemu:$* $< \ + $(if $V,,--quiet) $(if $(NOCACHE),--no-cache),\ + " BUILD $*") + +# Expand all the pre-requistes for each docker image and test combination +$(foreach i,$(DOCKER_IMAGES), \ + $(foreach t,$(DOCKER_TESTS) $(DOCKER_TOOLS), \ + $(eval .PHONY: docker-$t@$i) \ + $(eval docker-$t@$i: docker-image-$i docker-run-$t@$i) \ + ) \ + $(foreach t,$(DOCKER_TESTS), \ + $(eval docker-test: docker-$t@$i) \ + ) \ +) + +docker: + @echo 'Build QEMU and run tests inside Docker containers' + @echo + @echo 'Available targets:' + @echo + @echo ' docker: Print this help.' + @echo ' docker-test: Run all image/test combinations.' + @echo ' docker-clean: Kill and remove residual docker testing containers.' + @echo ' docker-TEST@IMAGE: Run "TEST" in container "IMAGE".' + @echo ' Note: "TEST" is one of the listed test name,' + @echo ' or a script name under $$QEMU_SRC/tests/docker/;' + @echo ' "IMAGE" is one of the listed container name."' + @echo ' docker-image: Build all images.' + @echo ' docker-image-IMAGE: Build image "IMAGE".' + @echo + @echo 'Available container images:' + @echo ' $(DOCKER_IMAGES)' + @echo + @echo 'Available tests:' + @echo ' $(DOCKER_TESTS)' + @echo + @echo 'Available tools:' + @echo ' $(DOCKER_TOOLS)' + @echo + @echo 'Special variables:' + @echo ' TARGET_LIST=a,b,c Override target list in builds.' + @echo ' IMAGES="a b c ..": Filters which images to build or run.' + @echo ' TESTS="x y z .." Filters which tests to run (for docker-test).' + @echo ' J=[0..9]* Overrides the -jN parameter for make commands' + @echo ' (default is 1)' + @echo ' DEBUG=1 Stop and drop to shell in the created container' + @echo ' before running the command.' + @echo ' NOCACHE=1 Ignore cache when build images.' + +docker-run-%: CMD = $(shell echo '$@' | sed -e 's/docker-run-\([^@]*\)@\(.*\)/\1/') +docker-run-%: IMAGE = $(shell echo '$@' | sed -e 's/docker-run-\([^@]*\)@\(.*\)/\2/') +docker-run-%: docker-qemu-src + @mkdir -p "$(DOCKER_CCACHE_DIR)" + @if test -z "$(IMAGE)" || test -z "$(CMD)"; \ + then echo "Invalid target"; exit 1; \ + fi + $(if $(filter $(TESTS),$(CMD)),$(if $(filter $(IMAGES),$(IMAGE)), \ + $(call quiet-command,\ + $(SRC_PATH)/tests/docker/docker.py run $(if $V,,--rm) \ + -t \ + $(if $(DEBUG),-i,--net=none) \ + -e TARGET_LIST=$(TARGET_LIST) \ + -e V=$V -e J=$J -e DEBUG=$(DEBUG)\ + -e CCACHE_DIR=/var/tmp/ccache \ + -v $$(realpath $(DOCKER_SRC_COPY)):/var/tmp/qemu:z$(COMMA)ro \ + -v $(DOCKER_CCACHE_DIR):/var/tmp/ccache:z \ + -w /var/tmp/qemu \ + qemu:$(IMAGE) \ + $(if $V,/bin/bash -x ,) \ + ./run \ + $(CMD); \ + , " RUN $(CMD) in $(IMAGE)"))) + +docker-clean: + $(call quiet-command, $(SRC_PATH)/tests/docker/docker.py clean) From ca853f0c76e39044df66e4afe0195552aad814ce Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Wed, 1 Jun 2016 12:25:18 +0800 Subject: [PATCH 05/16] docker: Add images MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Alex Bennée Signed-off-by: Fam Zheng Message-id: 1464755128-32490-6-git-send-email-famz@redhat.com --- tests/docker/dockerfiles/centos6.docker | 6 ++++++ tests/docker/dockerfiles/fedora.docker | 7 +++++++ tests/docker/dockerfiles/ubuntu.docker | 11 +++++++++++ 3 files changed, 24 insertions(+) create mode 100644 tests/docker/dockerfiles/centos6.docker create mode 100644 tests/docker/dockerfiles/fedora.docker create mode 100644 tests/docker/dockerfiles/ubuntu.docker diff --git a/tests/docker/dockerfiles/centos6.docker b/tests/docker/dockerfiles/centos6.docker new file mode 100644 index 0000000000..8f4fe46379 --- /dev/null +++ b/tests/docker/dockerfiles/centos6.docker @@ -0,0 +1,6 @@ +FROM centos:6 +RUN yum install -y \ + tar git make gcc g++ \ + zlib-devel glib2-devel SDL-devel pixman-devel \ + epel-release +RUN yum install -y libfdt-devel ccache diff --git a/tests/docker/dockerfiles/fedora.docker b/tests/docker/dockerfiles/fedora.docker new file mode 100644 index 0000000000..6251e45137 --- /dev/null +++ b/tests/docker/dockerfiles/fedora.docker @@ -0,0 +1,7 @@ +FROM fedora:23 +RUN dnf install -y \ + ccache git tar \ + glib2-devel pixman-devel zlib-devel SDL-devel libfdt-devel \ + gcc gcc-c++ clang make perl which bc findutils \ + mingw{32,64}-{pixman,glib2,gmp,SDL,pkg-config,gtk2,gtk3,gnutls,nettle,libtasn1,libjpeg-turbo,libpng,curl,libssh2,bzip2} +ENV FEATURES mingw clang diff --git a/tests/docker/dockerfiles/ubuntu.docker b/tests/docker/dockerfiles/ubuntu.docker new file mode 100644 index 0000000000..725a7ca5d0 --- /dev/null +++ b/tests/docker/dockerfiles/ubuntu.docker @@ -0,0 +1,11 @@ +FROM ubuntu:14.04 +RUN echo "deb http://archive.ubuntu.com/ubuntu/ trusty universe multiverse" >> \ + /etc/apt/sources.list +RUN apt-get update +RUN apt-get -y install \ + libusb-1.0-0-dev libiscsi-dev librados-dev libncurses5-dev \ + libseccomp-dev libgnutls-dev libssh2-1-dev libspice-server-dev \ + libspice-protocol-dev libnss3-dev libfdt-dev \ + libgtk-3-dev libvte-2.90-dev libsdl1.2-dev libpng12-dev libpixman-1-dev \ + git make ccache python-yaml gcc clang sparse +ENV FEATURES clang ccache pyyaml From b344aa9132e832127b7d740b5ae26ae9a2c453f0 Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Wed, 1 Jun 2016 12:25:19 +0800 Subject: [PATCH 06/16] docker: Add test runner MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's better to have a launcher for all tests, to make it easier to initialize and manage the environment. If "DEBUG=1" a shell prompt will show up before the test runs. Reviewed-by: Alex Bennée Signed-off-by: Fam Zheng Message-id: 1464755128-32490-7-git-send-email-famz@redhat.com --- tests/docker/run | 58 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100755 tests/docker/run diff --git a/tests/docker/run b/tests/docker/run new file mode 100755 index 0000000000..ec3d11934b --- /dev/null +++ b/tests/docker/run @@ -0,0 +1,58 @@ +#!/bin/bash -e +# +# Docker test runner +# +# Copyright (c) 2016 Red Hat Inc. +# +# Authors: +# Fam Zheng +# +# This work is licensed under the terms of the GNU GPL, version 2 +# or (at your option) any later version. See the COPYING file in +# the top-level directory. + +# Prepare the environment +. /etc/profile || true +export PATH=/usr/lib/ccache:$PATH + +if test -n "$J"; then + export MAKEFLAGS="$MAKEFLAGS -j$J" +fi + +# We are in the container so the whole file system belong to us +export TEST_DIR=/tmp/qemu-test +mkdir -p $TEST_DIR/{src,build,install} + +# Extract the source tarballs +tar -C $TEST_DIR/src -xzf qemu.tgz +for p in dtc pixman; do + if test -f $p.tgz; then + tar -C $TEST_DIR/src/$p -xzf $p.tgz + export FEATURES="$FEATURES $p" + fi +done + +export QEMU_SRC="$TEST_DIR/src" + +cd "$QEMU_SRC/tests/docker" + +CMD="$QEMU_SRC/tests/docker/$@" + +if test -n "$DEBUG"; then + echo "* Prepared to run command:" + echo " $CMD" + echo "* Hit Ctrl-D to continue, or type 'exit 1' to abort" + echo + $SHELL +fi + +if "$CMD"; then + exit 0 +elif test -n "$DEBUG"; then + echo "* Command failed:" + echo " $CMD" + echo "* Hit Ctrl-D to exit" + echo + # Force error after shell exits + $SHELL && exit 1 +fi From 3568f98ca56099309417a9bbf0e22435fa7094a5 Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Wed, 1 Jun 2016 12:25:20 +0800 Subject: [PATCH 07/16] docker: Add common.rc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "requires" checks the "FEATURE" environment for specified prerequisits, and skip the execution of test if not found. "build_qemu" is the central routine to compile QEMU for tests to call. Reviewed-by: Alex Bennée Signed-off-by: Fam Zheng Message-id: 1464755128-32490-8-git-send-email-famz@redhat.com --- tests/docker/common.rc | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100755 tests/docker/common.rc diff --git a/tests/docker/common.rc b/tests/docker/common.rc new file mode 100755 index 0000000000..74b89d6c1e --- /dev/null +++ b/tests/docker/common.rc @@ -0,0 +1,31 @@ +#!/bin/sh +# +# Common routines for docker test scripts. +# +# Copyright (c) 2016 Red Hat Inc. +# +# Authors: +# Fam Zheng +# +# This work is licensed under the terms of the GNU GPL, version 2 +# or (at your option) any later version. See the COPYING file in +# the top-level directory. + +requires() +{ + for c in $@; do + if ! echo "$FEATURES" | grep -wq -e "$c"; then + echo "Prerequisite '$c' not present, skip" + exit 0 + fi + done +} + +build_qemu() +{ + $QEMU_SRC/configure \ + --target-list="${TARGET_LIST}" \ + --prefix="$PWD/install" \ + "$@" + make $MAKEFLAGS +} From b7899d63c8780a69b690974de48d4ecabc773308 Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Wed, 1 Jun 2016 12:25:21 +0800 Subject: [PATCH 08/16] docker: Add quick test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Alex Bennée Signed-off-by: Fam Zheng Message-id: 1464755128-32490-9-git-send-email-famz@redhat.com --- tests/docker/test-quick | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100755 tests/docker/test-quick diff --git a/tests/docker/test-quick b/tests/docker/test-quick new file mode 100755 index 0000000000..07cdc59a10 --- /dev/null +++ b/tests/docker/test-quick @@ -0,0 +1,19 @@ +#!/bin/bash -e +# +# Quick compiling test that everyone already does. But why not automate it? +# +# Copyright (c) 2016 Red Hat Inc. +# +# Authors: +# Fam Zheng +# +# This work is licensed under the terms of the GNU GPL, version 2 +# or (at your option) any later version. See the COPYING file in +# the top-level directory. + +. common.rc + +DEF_TARGET_LIST="$(echo {x86_64,aarch64}-softmmu)" +TARGET_LIST=${TARGET_LIST:-$DEF_TARGET_LIST} \ +build_qemu +make check $MAKEFLAGS From d710ac871c1d4023528d41d1867413f123e14c93 Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Wed, 1 Jun 2016 12:25:22 +0800 Subject: [PATCH 09/16] docker: Add full test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This builds all available targets. Signed-off-by: Fam Zheng Reviewed-by: Alex Bennée Message-id: 1464755128-32490-10-git-send-email-famz@redhat.com --- tests/docker/test-full | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100755 tests/docker/test-full diff --git a/tests/docker/test-full b/tests/docker/test-full new file mode 100755 index 0000000000..fd9b798947 --- /dev/null +++ b/tests/docker/test-full @@ -0,0 +1,17 @@ +#!/bin/bash -e +# +# Compile all the targets. +# +# Copyright (c) 2016 Red Hat Inc. +# +# Authors: +# Fam Zheng +# +# This work is licensed under the terms of the GNU GPL, version 2 +# or (at your option) any later version. See the COPYING file in +# the top-level directory. + +. common.rc + +build_qemu +make check $MAKEFLAGS From c8908570dcb93e2675440787bacb3ad81efd6be9 Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Wed, 1 Jun 2016 12:25:23 +0800 Subject: [PATCH 10/16] docker: Add clang test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The (currently partially commented out) configure options are suggested by John Snow . Signed-off-by: Fam Zheng Reviewed-by: Alex Bennée Message-id: 1464755128-32490-11-git-send-email-famz@redhat.com --- tests/docker/test-clang | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100755 tests/docker/test-clang diff --git a/tests/docker/test-clang b/tests/docker/test-clang new file mode 100755 index 0000000000..6745dbeb83 --- /dev/null +++ b/tests/docker/test-clang @@ -0,0 +1,26 @@ +#!/bin/bash -e +# +# Compile and check with clang. +# +# Copyright (c) 2016 Red Hat Inc. +# +# Authors: +# Fam Zheng +# +# This work is licensed under the terms of the GNU GPL, version 2 +# or (at your option) any later version. See the COPYING file in +# the top-level directory. + +. common.rc + +requires clang + +OPTS="--enable-debug --cxx=clang++ --cc=clang --host-cc=clang" +# -fsanitize=undefined is broken on Fedora 23, skip it for now +# See also: https://bugzilla.redhat.com/show_bug.cgi?id=1263834 +#OPTS="$OPTS --extra-cflags=-fsanitize=undefined \ + #--extra-cflags=-fno-sanitize=float-divide-by-zero" +DEF_TARGET_LIST="$(echo {x86_64,aarch64}-softmmu)" +TARGET_LIST=${TARGET_LIST:-$DEF_TARGET_LIST} \ +build_qemu $OPTS +make $MAKEFLAGS check From c4f0eed1f33b107c08ae204ae06fd05b9b50410d Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Wed, 1 Jun 2016 12:25:24 +0800 Subject: [PATCH 11/16] docker: Add mingw test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Alex Bennée Signed-off-by: Fam Zheng Message-id: 1464755128-32490-12-git-send-email-famz@redhat.com --- tests/docker/test-mingw | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100755 tests/docker/test-mingw diff --git a/tests/docker/test-mingw b/tests/docker/test-mingw new file mode 100755 index 0000000000..c03757add8 --- /dev/null +++ b/tests/docker/test-mingw @@ -0,0 +1,34 @@ +#!/bin/bash -e +# +# Cross compile QEMU with mingw toolchain on Linux. +# +# Copyright (c) 2016 Red Hat Inc. +# +# Authors: +# Fam Zheng +# +# This work is licensed under the terms of the GNU GPL, version 2 +# or (at your option) any later version. See the COPYING file in +# the top-level directory. + +. common.rc + +requires mingw dtc + +for prefix in x86_64-w64-mingw32- i686-w64-mingw32-; do + TARGET_LIST=x86_64-softmmu,aarch64-softmmu \ + build_qemu --cross-prefix=$prefix \ + --enable-trace-backends=simple \ + --enable-debug \ + --enable-gnutls \ + --enable-nettle \ + --enable-curl \ + --enable-vnc \ + --enable-bzip2 \ + --enable-guest-agent \ + --with-sdlabi=1.2 \ + --with-gtkabi=2.0 + make clean + +done + From d5bd7891980926c075604ec6a1fd530301771443 Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Wed, 1 Jun 2016 12:25:25 +0800 Subject: [PATCH 12/16] docker: Add travis tool MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The script is not prefixed with test- so it won't run with "make docker-test", because it can take too long. Run it with "make docker-travis@ubuntu". Reviewed-by: Alex Bennée Signed-off-by: Fam Zheng Message-id: 1464755128-32490-13-git-send-email-famz@redhat.com --- tests/docker/travis | 21 ++++++++++++++++++ tests/docker/travis.py | 48 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100755 tests/docker/travis create mode 100755 tests/docker/travis.py diff --git a/tests/docker/travis b/tests/docker/travis new file mode 100755 index 0000000000..d345393ced --- /dev/null +++ b/tests/docker/travis @@ -0,0 +1,21 @@ +#!/bin/bash -e +# +# Mimic a travis testing matrix +# +# Copyright (c) 2016 Red Hat Inc. +# +# Authors: +# Fam Zheng +# +# This work is licensed under the terms of the GNU GPL, version 2 +# or (at your option) any later version. See the COPYING file in +# the top-level directory. + +. common.rc + +requires pyyaml +cmdfile=/tmp/travis_cmd_list.sh +$QEMU_SRC/tests/docker/travis.py $QEMU_SRC/.travis.yml > $cmdfile +chmod +x $cmdfile +cd "$QEMU_SRC" +$cmdfile diff --git a/tests/docker/travis.py b/tests/docker/travis.py new file mode 100755 index 0000000000..8dcc964da4 --- /dev/null +++ b/tests/docker/travis.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python +# +# Travis YAML config parser +# +# Copyright (c) 2016 Red Hat Inc. +# +# Authors: +# Fam Zheng +# +# This work is licensed under the terms of the GNU GPL, version 2 +# or (at your option) any later version. See the COPYING file in +# the top-level directory. + +import sys +import yaml +import itertools + +def load_yaml(fname): + return yaml.load(open(fname, "r").read()) + +def conf_iter(conf): + def env_to_list(env): + return env if isinstance(env, list) else [env] + global_env = conf["env"]["global"] + for entry in conf["matrix"]["include"]: + yield {"env": global_env + env_to_list(entry["env"]), + "compiler": entry["compiler"]} + for entry in itertools.product(conf["compiler"], + conf["env"]["matrix"]): + yield {"env": global_env + env_to_list(entry[1]), + "compiler": entry[0]} + +def main(): + if len(sys.argv) < 2: + sys.stderr.write("Usage: %s \n" % sys.argv[0]) + return 1 + conf = load_yaml(sys.argv[1]) + for config in conf_iter(conf): + print "(" + print "\n".join(config["env"]) + print "alias cc=" + config["compiler"] + print "\n".join(conf["before_script"]) + print "\n".join(conf["script"]) + print ")" + return 0 + +if __name__ == "__main__": + sys.exit(main()) From dc2e7eebd8603e36d63b6a1f5299bc49fe721b3b Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Wed, 1 Jun 2016 12:25:26 +0800 Subject: [PATCH 13/16] docs: Add text for tests/docker in build-system.txt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Alex Bennée Signed-off-by: Fam Zheng Message-id: 1464755128-32490-14-git-send-email-famz@redhat.com --- docs/build-system.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/build-system.txt b/docs/build-system.txt index 5ddddeaafb..2af1e668c5 100644 --- a/docs/build-system.txt +++ b/docs/build-system.txt @@ -438,6 +438,11 @@ top level Makefile, so anything defined in this file will influence the entire build system. Care needs to be taken when writing rules for tests to ensure they only apply to the unit test execution / build. +- tests/docker/Makefile.include + +Rules for Docker tests. Like tests/Makefile, this file is included +directly by the top level Makefile, anything defined in this file will +influence the entire build system. - po/Makefile From 35e0f959b51dd8d4df0add9c01bff29ec74828ea Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Wed, 1 Jun 2016 12:25:27 +0800 Subject: [PATCH 14/16] docker: Add EXTRA_CONFIGURE_OPTS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Whatever passed in this variable will be appended to all configure commands. Signed-off-by: Fam Zheng Reviewed-by: Alex Bennée Message-id: 1464755128-32490-15-git-send-email-famz@redhat.com --- tests/docker/Makefile.include | 3 +++ tests/docker/common.rc | 1 + 2 files changed, 4 insertions(+) diff --git a/tests/docker/Makefile.include b/tests/docker/Makefile.include index ef8bcaea59..2fd2ca3057 100644 --- a/tests/docker/Makefile.include +++ b/tests/docker/Makefile.include @@ -87,6 +87,8 @@ docker: @echo @echo 'Special variables:' @echo ' TARGET_LIST=a,b,c Override target list in builds.' + @echo ' EXTRA_CONFIGURE_OPTS="..."' + @echo ' Extra configure options.' @echo ' IMAGES="a b c ..": Filters which images to build or run.' @echo ' TESTS="x y z .." Filters which tests to run (for docker-test).' @echo ' J=[0..9]* Overrides the -jN parameter for make commands' @@ -108,6 +110,7 @@ docker-run-%: docker-qemu-src -t \ $(if $(DEBUG),-i,--net=none) \ -e TARGET_LIST=$(TARGET_LIST) \ + -e EXTRA_CONFIGURE_OPTS=$(EXTRA_CONFIGURE_OPTS) \ -e V=$V -e J=$J -e DEBUG=$(DEBUG)\ -e CCACHE_DIR=/var/tmp/ccache \ -v $$(realpath $(DOCKER_SRC_COPY)):/var/tmp/qemu:z$(COMMA)ro \ diff --git a/tests/docker/common.rc b/tests/docker/common.rc index 74b89d6c1e..c493eebd45 100755 --- a/tests/docker/common.rc +++ b/tests/docker/common.rc @@ -26,6 +26,7 @@ build_qemu() $QEMU_SRC/configure \ --target-list="${TARGET_LIST}" \ --prefix="$PWD/install" \ + $EXTRA_CONFIGURE_OPTS \ "$@" make $MAKEFLAGS } From 8a49e97f4524c97aafb2f8516aa7d49f7656066a Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Wed, 1 Jun 2016 12:25:28 +0800 Subject: [PATCH 15/16] MAINTAINERS: Add tests/docker MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Alex Bennée Signed-off-by: Fam Zheng Message-id: 1464755128-32490-16-git-send-email-famz@redhat.com --- MAINTAINERS | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 3c949d5a97..091272e1a2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1615,3 +1615,10 @@ Build system architecture M: Daniel P. Berrange S: Odd Fixes F: docs/build-system.txt + +Docker testing +-------------- +Docker based testing framework and cases +M: Fam Zheng +S: Maintained +F: tests/docker/ From 0bc7a6f3079af7b96e863c6eedef37a86abe1e24 Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Wed, 1 Jun 2016 17:21:24 +0800 Subject: [PATCH 16/16] .gitignore: Ignore docker source copy Signed-off-by: Fam Zheng --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 88a80ff4a5..38ee1c5681 100644 --- a/.gitignore +++ b/.gitignore @@ -108,4 +108,5 @@ cscope.* tags TAGS +docker-src.* *~