POLYGENE-221 build & internal test-support: introduce Docker fixtures
Project: http://git-wip-us.apache.org/repos/asf/polygene-java/repo Commit: http://git-wip-us.apache.org/repos/asf/polygene-java/commit/78422451 Tree: http://git-wip-us.apache.org/repos/asf/polygene-java/tree/78422451 Diff: http://git-wip-us.apache.org/repos/asf/polygene-java/diff/78422451 Branch: refs/heads/develop Commit: 78422451aea7ce59bfb4b8d089273c272c0f7244 Parents: 7c3651f Author: Paul Merlin <[email protected]> Authored: Mon Jan 9 18:40:52 2017 +0100 Committer: Paul Merlin <[email protected]> Committed: Mon Jan 9 18:56:58 2017 +0100 ---------------------------------------------------------------------- buildSrc/build.gradle | 1 + .../polygene/gradle/code/CodePlugin.groovy | 1 + .../internals/InternalDockerPlugin.groovy | 52 ++++++++++++++ .../polygene-internal-docker.properties | 18 +++++ dependencies.gradle | 2 + internals/testsupport-internal/build.gradle | 1 + .../polygene/test/internal/DockerRule.java | 74 ++++++++++++++++++++ .../src/docs/tutorials/howto-build-system.txt | 25 ++++--- 8 files changed, 163 insertions(+), 11 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/polygene-java/blob/78422451/buildSrc/build.gradle ---------------------------------------------------------------------- diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index aa94907..80a36a0 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -33,6 +33,7 @@ dependencies { compile 'org.hibernate.build.gradle:gradle-maven-publish-auth:2.0.1' compile 'org.apache.httpcomponents:httpclient:4.5.2' compile 'org.apache.httpcomponents:httpmime:4.5.2' + compile 'gradle.plugin.com.palantir.gradle.docker:gradle-docker:0.9.2' testCompile 'junit:junit:4.12' testCompile( 'org.spockframework:spock-core:1.0-groovy-2.4' ) { exclude module: 'groovy-all' } http://git-wip-us.apache.org/repos/asf/polygene-java/blob/78422451/buildSrc/src/main/groovy/org/apache/polygene/gradle/code/CodePlugin.groovy ---------------------------------------------------------------------- diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/code/CodePlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/code/CodePlugin.groovy index 6c143c8..1de5f10 100644 --- a/buildSrc/src/main/groovy/org/apache/polygene/gradle/code/CodePlugin.groovy +++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/code/CodePlugin.groovy @@ -122,6 +122,7 @@ class CodePlugin implements Plugin<Project> project.delete testDir } } + testTask.inputs.property( 'polygeneTestSupportDockerHostEnv', System.getenv( 'DOCKER_HOST' ) ) } } http://git-wip-us.apache.org/repos/asf/polygene-java/blob/78422451/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/internals/InternalDockerPlugin.groovy ---------------------------------------------------------------------- diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/internals/InternalDockerPlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/internals/InternalDockerPlugin.groovy new file mode 100644 index 0000000..7aed3d4 --- /dev/null +++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/internals/InternalDockerPlugin.groovy @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.polygene.gradle.structure.internals + +import com.palantir.gradle.docker.DockerExtension +import com.palantir.gradle.docker.PalantirDockerPlugin +import groovy.transform.CompileStatic +import org.apache.polygene.gradle.BasePlugin +import org.apache.polygene.gradle.code.PublishNaming +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.Task +import org.gradle.language.base.plugins.LifecycleBasePlugin + +@CompileStatic +class InternalDockerPlugin implements Plugin<Project> +{ + @Override + void apply( Project project ) + { + project.plugins.apply BasePlugin + project.plugins.apply PalantirDockerPlugin + def dockerExtension = project.extensions.getByType( DockerExtension ) + dockerExtension.name = "org.apache.polygene:${ PublishNaming.publishedNameFor( project.path ) }" + dockerExtension.dockerfile = 'src/main/docker/Dockerfile' + dockerExtension.files 'src/main/docker' + def dockerHost = System.getenv( 'DOCKER_HOST' ) as Object + [ project.tasks.getByName( 'dockerClean' ), + project.tasks.getByName( 'dockerPrepare' ), + project.tasks.getByName( 'docker' ) + ].each { Task dockerTask -> + dockerTask.inputs.property 'dockerHostEnv', dockerHost + dockerTask.onlyIf { dockerHost } + } + project.tasks.getByName( LifecycleBasePlugin.BUILD_TASK_NAME ).dependsOn 'docker' + } +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/78422451/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-internal-docker.properties ---------------------------------------------------------------------- diff --git a/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-internal-docker.properties b/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-internal-docker.properties new file mode 100644 index 0000000..60290a5 --- /dev/null +++ b/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-internal-docker.properties @@ -0,0 +1,18 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +implementation-class=org.apache.polygene.gradle.structure.internals.InternalDockerPlugin http://git-wip-us.apache.org/repos/asf/polygene-java/blob/78422451/dependencies.gradle ---------------------------------------------------------------------- diff --git a/dependencies.gradle b/dependencies.gradle index 778a54e..48d7f27 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -170,6 +170,7 @@ dependencies.libraries << [ def antVersion = '1.9.7' def awaitilityVersion = '2.0.0' def dnsJavaVersion = '2.1.7' +def dockerJUnitVersion = '0.3' def easyMockVersion = '3.4' def embedMongoVersion = '1.50.5' def h2Version = '1.4.193' @@ -186,6 +187,7 @@ dependencies.libraries << [ awaitility : "org.awaitility:awaitility:$awaitilityVersion", derby : "org.apache.derby:derby:$derbyVersion", dnsjava : "dnsjava:dnsjava:$dnsJavaVersion", + docker_junit : "com.github.tdomzal:junit-docker-rule:$dockerJUnitVersion", easymock : "org.easymock:easymock:$easyMockVersion", embed_mongo : "de.flapdoodle.embed:de.flapdoodle.embed.mongo:$embedMongoVersion", h2 : "com.h2database:h2:$h2Version", http://git-wip-us.apache.org/repos/asf/polygene-java/blob/78422451/internals/testsupport-internal/build.gradle ---------------------------------------------------------------------- diff --git a/internals/testsupport-internal/build.gradle b/internals/testsupport-internal/build.gradle index 5c0c2b3..6503990 100644 --- a/internals/testsupport-internal/build.gradle +++ b/internals/testsupport-internal/build.gradle @@ -20,6 +20,7 @@ apply plugin: 'polygene-internal' dependencies { compile polygene.core.testsupport + compile libraries.docker_junit runtime polygene.core.runtime } http://git-wip-us.apache.org/repos/asf/polygene-java/blob/78422451/internals/testsupport-internal/src/main/java/org/apache/polygene/test/internal/DockerRule.java ---------------------------------------------------------------------- diff --git a/internals/testsupport-internal/src/main/java/org/apache/polygene/test/internal/DockerRule.java b/internals/testsupport-internal/src/main/java/org/apache/polygene/test/internal/DockerRule.java new file mode 100644 index 0000000..cea44c8 --- /dev/null +++ b/internals/testsupport-internal/src/main/java/org/apache/polygene/test/internal/DockerRule.java @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.polygene.test.internal; + +import java.util.Collections; +import java.util.Map; +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; +import pl.domzal.junit.docker.rule.DockerRuleBuilder; +import pl.domzal.junit.docker.rule.WaitFor; + +import static org.junit.Assume.assumeNotNull; + +public class DockerRule implements TestRule +{ + private final String dockerHost = System.getenv( "DOCKER_HOST" ); + private final pl.domzal.junit.docker.rule.DockerRule dockerRule; + + public DockerRule( String image, int... portsToWaitFor ) + { + this( image, Collections.emptyMap(), portsToWaitFor ); + } + + public DockerRule( String image, Map<String, String> environment, int... portsToWaitFor ) + { + if( dockerHost == null ) + { + dockerRule = null; + } + else + { + DockerRuleBuilder builder = pl.domzal.junit.docker.rule.DockerRule + .builder() + .imageName( "org.apache.polygene:org.apache.polygene.internal.docker-" + image ) + .publishAllPorts( true ) + .waitFor( WaitFor.tcpPort( portsToWaitFor ) ); + environment.entrySet().forEach( entry -> builder.env( entry.getKey(), entry.getValue() ) ); + dockerRule = builder.build(); + } + } + + @Override + public Statement apply( Statement base, Description description ) + { + assumeNotNull( dockerHost ); + return dockerRule.apply( base, description ); + } + + public String getDockerHost() + { + return dockerRule.getDockerHost(); + } + + public int getExposedContainerPort( String containerPort ) + { + return Integer.valueOf( dockerRule.getExposedContainerPort( containerPort ) ); + } +} http://git-wip-us.apache.org/repos/asf/polygene-java/blob/78422451/manual/src/docs/tutorials/howto-build-system.txt ---------------------------------------------------------------------- diff --git a/manual/src/docs/tutorials/howto-build-system.txt b/manual/src/docs/tutorials/howto-build-system.txt index 04edd91..1a5fe9d 100644 --- a/manual/src/docs/tutorials/howto-build-system.txt +++ b/manual/src/docs/tutorials/howto-build-system.txt @@ -163,22 +163,25 @@ You'll find theses tests across the whole SDK. === Unit tests requiring external services === Among unit tests, some require an external service to be run. -For example, the MongoDB EntityStore extension requires an actual MongoDB server to run its tests. +For example, the Redis EntityStore extension requires an actual Redis server to run its tests. NOTE: The HTML test reports generated by Gradle shows skipped tests. -All thoses tests should be part of the default build and check if the service is available at its default location -on +localhost+ and skip if not. -This is easily achieved using http://junit.sourceforge.net/javadoc/org/junit/Assume.html[JUnit assumptions]. +Testing against external services is automated using Docker and is enabled if you have the +`DOCKER_HOST` environment variable set. +The build creates the necessary Docker images and start/stop containers around the tests. -We'll list here services that the unit tests will use if available. +The simplest way to get this running is to use `docker-machine` to create a development Docker virtual machine +where all images will be built and containers started: -- Memcached, ASCII protocol, no authentication on +localhost:4444+ for +extensions/cache-memcache+ -- MongoDB without authentication on +localhost:27017+ for +extensions/entitystore-mongodb+ -- Riak without authentication on +localhost:8087+ for +extensions/entitystore-riak+ -- Redis without authentication on +localhost:4444+ for +extensions/entitystore-redis+ -- PostgreSQL for +extensions/entitystore-sql+ and +extensions/indexing-sql+ (need setup, see test source) -- MySQL for +extensions/entitystore-sql+ (need setup, see test source) +[source,bash] +---- +docker-machine create dev +docker-machine start dev +eval $(docker-machine env dev) +---- + +The last stanza set environment variables for Docker to use the newly created Docker virtual machine. === Performance tests ===
