mirror of
https://github.com/google/nomulus.git
synced 2025-04-29 19:47:51 +02:00
* Run cross-release SQL integration tests Run SQL integration tests across arbitrary schema and server releases. Refer to integration/README.md in this change for more information. TESTED=Cloud build changes tested with cloud-build-local Used the published jars to test sqlIntegration task locally.
902 lines
33 KiB
Groovy
902 lines
33 KiB
Groovy
// Copyright 2019 The Nomulus Authors. All Rights Reserved.
|
|
//
|
|
// Licensed 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.
|
|
|
|
import java.lang.reflect.Constructor
|
|
|
|
plugins {
|
|
id 'java-library'
|
|
id 'maven-publish'
|
|
}
|
|
|
|
// Path to code generated by ad hoc tasks in this project. A separate path is
|
|
// used for easy inspection.
|
|
def generatedDir = "${project.buildDir}/generated/source/custom/main"
|
|
def resourcesDir = "${project.buildDir}/resources/main"
|
|
def screenshotsDir = "${project.buildDir}/screenshots"
|
|
def screenshotsForGoldensDir = "${project.buildDir}/screenshots_for_goldens"
|
|
def newGoldensDir = "${project.buildDir}/new_golden_images"
|
|
def goldensDir =
|
|
"${javaTestDir}/google/registry/webdriver/goldens/chrome-linux"
|
|
def jsDir = "${project.projectDir}/src/main/javascript"
|
|
|
|
// Tests that conflict with (mostly unidentified) members of the main test
|
|
// suite. It is unclear if they are offenders (i.e., those that pollute global
|
|
// state) or victims.
|
|
// TODO(weiminyu): identify cause and fix offending tests.
|
|
def outcastTestPatterns = [
|
|
// Problem seems to lie with AppEngine TaskQueue for test.
|
|
"google/registry/batch/DeleteContactsAndHostsActionTest.*",
|
|
"google/registry/batch/RefreshDnsOnHostRenameActionTest.*",
|
|
"google/registry/flows/CheckApiActionTest.*",
|
|
"google/registry/flows/EppLifecycleHostTest.*",
|
|
"google/registry/flows/domain/DomainCreateFlowTest.*",
|
|
"google/registry/flows/domain/DomainUpdateFlowTest.*",
|
|
"google/registry/tools/CreateDomainCommandTest.*",
|
|
"google/registry/tools/server/CreatePremiumListActionTest.*",
|
|
]
|
|
|
|
// Tests that fail when running Gradle in a docker container, e. g. when
|
|
// building the release artifacts in Google Cloud Build.
|
|
def dockerIncompatibleTestPatterns = [
|
|
// The webdriver tests start headless Chrome in a Docker container,
|
|
// resulting in Docker-in-Docker complications. Likewise,
|
|
// GenerateSqlSchemaCommandTest launches postgresql in a docker container.
|
|
"google/registry/webdriver/*",
|
|
"google/registry/tools/GenerateSqlSchemaCommandTest.*",
|
|
// PathParameterTest includes tests which validate that file permissions are
|
|
// respected. However when running in Docker the user is root by default, so
|
|
// every file is read/write-able. There is no way to exclude specific test
|
|
// methods, so we exclude the whole test class.
|
|
"google/registry/tools/params/PathParameterTest.*",
|
|
"google/registry/persistence/PersistenceModuleTest.*",
|
|
]
|
|
|
|
// Tests that conflict with members of both the main test suite and the
|
|
// outcast suite. They seem to be affected by global states outside of
|
|
// Nomulus classes, e.g., threads and objects retained by frameworks.
|
|
// TODO(weiminyu): identify cause and fix offending tests.
|
|
def fragileTestPatterns = [
|
|
// Problem seems to lie with AppEngine TaskQueue for test.
|
|
"google/registry/cron/TldFanoutActionTest.*",
|
|
// Test Datastore inexplicably aborts transaction.
|
|
"google/registry/model/tmch/ClaimsListShardTest.*",
|
|
// Creates large object (64MBytes), occasionally throws OOM error.
|
|
"google/registry/model/server/KmsSecretRevisionTest.*",
|
|
] + dockerIncompatibleTestPatterns
|
|
|
|
sourceSets {
|
|
main {
|
|
java {
|
|
srcDirs += generatedDir
|
|
// Javadoc API is deprecated in Java 11 and removed in Java 12.
|
|
// TODO(jianglai): re-enable after migrating to the new Javadoc API
|
|
if ((JavaVersion.current().majorVersion as Integer) >= 11) {
|
|
exclude 'google/registry/documentation/**'
|
|
}
|
|
}
|
|
resources {
|
|
exclude '**/*.xjb'
|
|
}
|
|
}
|
|
test {
|
|
java {
|
|
// Javadoc API is deprecated in Java 11 and removed in Java 12.
|
|
// TODO(jianglai): re-enable after migrating to the new Javadoc API
|
|
if ((JavaVersion.current().majorVersion as Integer) >= 11) {
|
|
exclude 'google/registry/documentation/**'
|
|
}
|
|
}
|
|
resources {
|
|
exclude '**/*.xjb', '**/*.xsd'
|
|
}
|
|
}
|
|
}
|
|
|
|
processTestResources {
|
|
exclude '**/webdriver/*'
|
|
}
|
|
|
|
configurations {
|
|
css
|
|
jaxb
|
|
soy
|
|
closureCompiler
|
|
|
|
// Published jars that are used for server/schema compatibility tests.
|
|
// See <a href="../integration/README.md">the integration project</a>
|
|
// for details.
|
|
nomulus_test
|
|
|
|
// Exclude non-canonical servlet-api jars. Our AppEngine deployment uses
|
|
// javax.servlet:servlet-api:2.5
|
|
// For reasons we do not understand, marking the following dependencies as
|
|
// compileOnly instead of compile does not exclude them from runtimeClasspath.
|
|
all {
|
|
// servlet-api:3.1 pulled in but not used by soy compiler
|
|
exclude group: 'javax.servlet', module: 'javax.servlet-api'
|
|
// Jetty's servlet-api:2.5 implementation, pulled in by other Jetty jars
|
|
exclude group: 'org.mortbay.jetty', module: 'servlet-api'
|
|
}
|
|
}
|
|
|
|
// Known issues:
|
|
// - The (test/)compile/runtime labels are deprecated. We continue using these
|
|
// labels due to nebula-lint.
|
|
// TODO(weiminyu): switch to api/implementation labels.
|
|
// See https://github.com/nebula-plugins/gradle-lint-plugin/issues/130 for
|
|
// issue status.
|
|
// - Nebula-lint's conflict between unused and undeclared dependency check.
|
|
// If an undeclared dependency is added, the unused-dependency check will flag
|
|
// it. For now we wrap affected dependency in gradleLint.ignore block.
|
|
// TODO(weiminyu): drop gradleLint.ignore block when issue is fixed.
|
|
// See https://github.com/nebula-plugins/gradle-lint-plugin/issues/181 for
|
|
// issue status.
|
|
dependencies {
|
|
def deps = rootProject.dependencyMap
|
|
|
|
// Custom-built objectify jar at commit ecd5165, included in Nomulus
|
|
// release.
|
|
implementation files(
|
|
"${rootDir}/third_party/objectify/v4_1/objectify-4.1.3.jar")
|
|
testImplementation project(':third_party')
|
|
|
|
testRuntime files(sourceSets.test.resources.srcDirs)
|
|
|
|
compile deps['com.beust:jcommander']
|
|
compile deps['com.google.api-client:google-api-client']
|
|
compile deps['com.google.monitoring-client:metrics']
|
|
compile deps['com.google.monitoring-client:stackdriver']
|
|
compile deps['com.google.api-client:google-api-client-java6']
|
|
compile deps['com.google.apis:google-api-services-admin-directory']
|
|
compile deps['com.google.apis:google-api-services-appengine']
|
|
compile deps['com.google.apis:google-api-services-bigquery']
|
|
compile deps['com.google.apis:google-api-services-cloudkms']
|
|
compile deps['com.google.apis:google-api-services-dataflow']
|
|
compile deps['com.google.apis:google-api-services-dns']
|
|
compile deps['com.google.apis:google-api-services-drive']
|
|
compile deps['com.google.apis:google-api-services-groupssettings']
|
|
compile deps['com.google.apis:google-api-services-monitoring']
|
|
compile deps['com.google.apis:google-api-services-sheets']
|
|
testCompile deps['com.google.appengine:appengine-api-stubs']
|
|
compile deps['com.google.appengine.tools:appengine-gcs-client']
|
|
compile deps['com.google.appengine.tools:appengine-mapreduce']
|
|
compile deps['com.google.appengine.tools:appengine-pipeline']
|
|
compile deps['com.google.appengine:appengine-remote-api']
|
|
compile deps['com.google.auth:google-auth-library-credentials']
|
|
compile deps['com.google.auth:google-auth-library-oauth2-http']
|
|
runtimeOnly deps['com.google.cloud.sql:postgres-socket-factory']
|
|
compile deps['com.google.code.gson:gson']
|
|
compile deps['com.google.auto.value:auto-value-annotations']
|
|
compile deps['com.google.code.findbugs:jsr305']
|
|
compile deps['com.google.dagger:dagger']
|
|
compile deps['com.google.errorprone:error_prone_annotations']
|
|
compile deps['com.google.flogger:flogger']
|
|
runtime deps['com.google.flogger:flogger-system-backend']
|
|
compile deps['com.google.guava:guava']
|
|
gradleLint.ignore('unused-dependency') {
|
|
compile deps['com.google.gwt:gwt-user']
|
|
}
|
|
compile deps['com.google.http-client:google-http-client']
|
|
compile deps['com.google.http-client:google-http-client-appengine']
|
|
compile deps['com.google.http-client:google-http-client-jackson2']
|
|
compile deps['com.google.oauth-client:google-oauth-client']
|
|
compile deps['com.google.oauth-client:google-oauth-client-java6']
|
|
compile deps['com.google.oauth-client:google-oauth-client-jetty']
|
|
compile deps['com.google.re2j:re2j']
|
|
compile deps['com.google.template:soy']
|
|
compile deps['com.googlecode.json-simple:json-simple']
|
|
compile deps['com.jcraft:jsch']
|
|
testCompile deps['com.thoughtworks.qdox:qdox']
|
|
compile deps['dnsjava:dnsjava']
|
|
testCompile deps['io.github.classgraph:classgraph']
|
|
testRuntime deps['io.github.java-diff-utils:java-diff-utils']
|
|
testCompile deps['javax.annotation:javax.annotation-api']
|
|
testCompile deps['javax.annotation:jsr250-api']
|
|
compile deps['javax.inject:javax.inject']
|
|
compile deps['javax.mail:mail']
|
|
compile deps['javax.persistence:javax.persistence-api']
|
|
compile deps['javax.servlet:servlet-api']
|
|
compile deps['javax.xml.bind:jaxb-api']
|
|
compile deps['jline:jline']
|
|
compile deps['joda-time:joda-time']
|
|
compile deps['org.apache.avro:avro']
|
|
testCompile deps['org.apache.beam:beam-runners-direct-java']
|
|
compile deps['org.apache.beam:beam-runners-google-cloud-dataflow-java']
|
|
compile deps['org.apache.beam:beam-sdks-java-core']
|
|
compile deps['org.apache.beam:beam-sdks-java-extensions-google-cloud-platform-core']
|
|
compile deps['org.apache.beam:beam-sdks-java-io-google-cloud-platform']
|
|
testCompile deps['org.apache.commons:commons-lang3']
|
|
testCompile deps['org.apache.commons:commons-text']
|
|
testCompile deps['org.apache.ftpserver:ftplet-api']
|
|
testCompile deps['org.apache.ftpserver:ftpserver-core']
|
|
compile deps['org.apache.httpcomponents:httpclient']
|
|
compile deps['org.apache.httpcomponents:httpcore']
|
|
testCompile deps['org.apache.sshd:sshd-core']
|
|
testCompile deps['org.apache.sshd:sshd-scp']
|
|
testCompile deps['org.apache.sshd:sshd-sftp']
|
|
testCompile deps['org.apache.tomcat:tomcat-annotations-api']
|
|
compile deps['org.bouncycastle:bcpg-jdk15on']
|
|
testCompile deps['org.bouncycastle:bcpkix-jdk15on']
|
|
compile deps['org.bouncycastle:bcprov-jdk15on']
|
|
runtime deps['org.glassfish.jaxb:jaxb-runtime']
|
|
compile deps['org.hibernate:hibernate-core']
|
|
compile deps['org.joda:joda-money']
|
|
compile deps['org.json:json']
|
|
testCompile deps['org.mortbay.jetty:jetty']
|
|
runtimeOnly deps['org.postgresql:postgresql']
|
|
testCompile deps['org.seleniumhq.selenium:selenium-api']
|
|
testCompile deps['org.seleniumhq.selenium:selenium-chrome-driver']
|
|
testCompile deps['org.seleniumhq.selenium:selenium-java']
|
|
testCompile deps['org.seleniumhq.selenium:selenium-remote-driver']
|
|
testCompile deps['org.testcontainers:jdbc']
|
|
compile deps['org.testcontainers:postgresql']
|
|
testCompile deps['org.testcontainers:selenium']
|
|
testCompile deps['org.testcontainers:testcontainers']
|
|
compile deps['xerces:xmlParserAPIs']
|
|
compile deps['xpp3:xpp3']
|
|
// This dependency must come after javax.mail:mail as it would otherwise
|
|
// shadow classes in package javax.mail with its own implementation.
|
|
compile deps['com.google.appengine:appengine-api-1.0-sdk']
|
|
|
|
// Known issue: nebula-lint misses inherited dependency.
|
|
compile project(':common')
|
|
testCompile project(path: ':common', configuration: 'testing')
|
|
compile project(':third_party')
|
|
compile project(':util')
|
|
// Import NomulusPostreSql from ':db' for compile but exclude dependencies.
|
|
compile project(path: ':db', configuration: 'compileApi')
|
|
testRuntime project(':db')
|
|
|
|
// Include auto-value in compile until nebula-lint understands
|
|
// annotationProcessor
|
|
gradleLint.ignore('unused-dependency') {
|
|
compile deps['com.google.auto.value:auto-value']
|
|
}
|
|
annotationProcessor deps['com.google.auto.value:auto-value']
|
|
testAnnotationProcessor deps['com.google.auto.value:auto-value']
|
|
annotationProcessor deps['com.google.dagger:dagger-compiler']
|
|
testAnnotationProcessor deps['com.google.dagger:dagger-compiler']
|
|
|
|
testCompile deps['com.google.appengine:appengine-testing']
|
|
testCompile deps['com.google.guava:guava-testlib']
|
|
testCompile deps['com.google.monitoring-client:contrib']
|
|
testCompile deps['com.google.truth:truth']
|
|
testCompile deps['com.google.truth.extensions:truth-java8-extension']
|
|
testCompile deps['org.hamcrest:hamcrest-all']
|
|
testCompile deps['org.hamcrest:hamcrest-core']
|
|
testCompile deps['org.hamcrest:hamcrest-library']
|
|
compile deps['org.hibernate:hibernate-hikaricp']
|
|
testCompile deps['junit:junit']
|
|
testCompile deps['org.mockito:mockito-core']
|
|
runtime deps['org.postgresql:postgresql']
|
|
|
|
// Indirect dependency found by undeclared-dependency check. Such
|
|
// dependencies should go after all other compile and testCompile
|
|
// dependencies to avoid overriding them accidentally.
|
|
compile deps['com.google.oauth-client:google-oauth-client-java6']
|
|
|
|
// Dependencies needed for jaxb compilation.
|
|
// Use jaxb 2.2.11 because 2.3 is known to break the Ant task we use.
|
|
// TODO: upgrade jaxb versions to 2.4.0, already in beta by Sept 2018
|
|
jaxb deps['javax.xml.bind:jaxb-api']
|
|
jaxb deps['com.sun.activation:javax.activation']
|
|
jaxb deps['com.sun.xml.bind:jaxb-xjc']
|
|
jaxb deps['com.sun.xml.bind:jaxb-impl']
|
|
jaxb deps['com.sun.xml.bind:jaxb-osgi']
|
|
|
|
// Dependency needed for soy to java compilation.
|
|
soy deps['com.google.template:soy']
|
|
|
|
// Dependencies needed for compiling stylesheets to javascript
|
|
css deps['com.google.closure-stylesheets:closure-stylesheets']
|
|
css deps['args4j:args4j']
|
|
|
|
// Tool dependencies. used for doc generation.
|
|
compile files("${System.properties['java.home']}/../lib/tools.jar")
|
|
|
|
closureCompiler deps['com.google.javascript:closure-compiler']
|
|
}
|
|
|
|
task jaxbToJava {
|
|
def xsdFilesDir = "${javaDir}/google/registry/xml/xsd"
|
|
def bindingsFile = "${javaDir}/google/registry/xjc/bindings.xjb"
|
|
def pkgInfoTemplate = "${javaDir}/google/registry/xjc/package-info.java.in"
|
|
def pkgInfoMap = "${javaDir}/google/registry/xjc/package-info.map"
|
|
def outputDir = "${generatedDir}/google/registry/xjc"
|
|
|
|
inputs.dir xsdFilesDir
|
|
inputs.files bindingsFile, pkgInfoTemplate, pkgInfoMap
|
|
outputs.dir outputDir
|
|
|
|
doLast {
|
|
file(generatedDir).mkdirs()
|
|
|
|
// Temp dir to hold schema and bindings files. Files must be in the same
|
|
// directory because the bindings (.xjb) file does not declare relative
|
|
// paths to schema (.xsd) files.
|
|
def xjcTempSourceDir = file("${temporaryDir}/xjc")
|
|
xjcTempSourceDir.mkdirs()
|
|
ant.copy(
|
|
todir: "${xjcTempSourceDir}",
|
|
overwrite: true) {
|
|
fileSet(
|
|
dir: xsdFilesDir,
|
|
includes: '**.xsd')
|
|
}
|
|
ant.copy(
|
|
todir: "${xjcTempSourceDir}",
|
|
overwrite: true,
|
|
file: bindingsFile)
|
|
ant.taskdef(
|
|
name: 'xjc',
|
|
classname: 'com.sun.tools.xjc.XJCTask',
|
|
classpath: configurations.jaxb.asPath)
|
|
ant.xjc(
|
|
destdir: "${generatedDir}",
|
|
binding: "${xjcTempSourceDir}/bindings.xjb",
|
|
removeOldOutput: 'yes', extension: 'true') {
|
|
project.fileTree(
|
|
dir: new File("$xjcTempSourceDir"),
|
|
include: ['**/*.xsd'])
|
|
.addToAntBuilder(ant, 'schema', FileCollection.AntType.FileSet)
|
|
// -npa: do not generate package-info.java files. They will be generated
|
|
// below.
|
|
arg(line: '-npa -quiet -extension')
|
|
}
|
|
new File(pkgInfoMap).eachLine { line ->
|
|
def (packageName, namespace) = line.split()
|
|
ant.copy(
|
|
tofile: "${outputDir}/${packageName}/package-info.java",
|
|
overwrite: true,
|
|
file: "${pkgInfoTemplate}") {
|
|
filterSet() {
|
|
filter(token: 'PACKAGE', value: packageName)
|
|
filter(token: 'NAMESPACE', value: namespace)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
task soyToJava {
|
|
// Relative paths of soy directories.
|
|
def spec11SoyDir = "google/registry/reporting/spec11/soy"
|
|
def toolsSoyDir = "google/registry/tools/soy"
|
|
def uiSoyDir = "google/registry/ui/soy"
|
|
def registrarSoyDir = "google/registry/ui/soy/registrar"
|
|
|
|
def soyRelativeDirs = [
|
|
spec11SoyDir, toolsSoyDir, uiSoyDir, registrarSoyDir,
|
|
]
|
|
soyRelativeDirs.each {
|
|
inputs.dir "${resourcesSourceDir}/${it}"
|
|
outputs.dir "${generatedDir}/${it}"
|
|
}
|
|
|
|
ext.soyToJava = { javaPackage, outputDirectory, soyFiles ->
|
|
javaexec {
|
|
main = "com.google.template.soy.SoyParseInfoGenerator"
|
|
classpath configurations.soy
|
|
args "--javaPackage", "${javaPackage}",
|
|
"--outputDirectory", "${outputDirectory}",
|
|
"--javaClassNameSource", "filename",
|
|
"--allowExternalCalls", "true",
|
|
"--srcs", "${soyFiles.join(',')}"
|
|
}
|
|
}
|
|
|
|
doLast {
|
|
soyToJava('google.registry.tools.soy',
|
|
"${generatedDir}/${toolsSoyDir}",
|
|
fileTree(
|
|
dir: "${resourcesSourceDir}/${toolsSoyDir}",
|
|
include: ['**/*.soy']))
|
|
|
|
soyToJava('google.registry.ui.soy.registrar',
|
|
"${generatedDir}/${registrarSoyDir}",
|
|
fileTree(
|
|
dir: "${resourcesSourceDir}/${registrarSoyDir}",
|
|
include: ['**/*.soy']))
|
|
|
|
soyToJava('google.registry.ui.soy',
|
|
"${generatedDir}/${uiSoyDir}",
|
|
files {
|
|
file("${resourcesSourceDir}/${uiSoyDir}").listFiles()
|
|
}.filter {
|
|
it.name.endsWith(".soy")
|
|
})
|
|
|
|
soyToJava('google.registry.reporting.spec11.soy',
|
|
"${generatedDir}/${spec11SoyDir}",
|
|
fileTree(
|
|
dir: "${resourcesSourceDir}/${spec11SoyDir}",
|
|
include: ['**/*.soy']))
|
|
}
|
|
}
|
|
|
|
task soyToJS {
|
|
def rootSoyDirectory = "${resourcesSourceDir}/google/registry/ui/soy"
|
|
def outputSoyDirectory = "${generatedDir}/google/registry/ui/soy"
|
|
inputs.dir rootSoyDirectory
|
|
outputs.dir outputSoyDirectory
|
|
|
|
ext.soyToJS = { outputDirectory, soyFiles , deps->
|
|
javaexec {
|
|
main = "com.google.template.soy.SoyToJsSrcCompiler"
|
|
classpath configurations.soy
|
|
|
|
args "--outputPathFormat", "${outputDirectory}/{INPUT_FILE_NAME}.js",
|
|
"--allowExternalCalls", "false",
|
|
"--srcs", "${soyFiles.join(',')}",
|
|
"--shouldProvideRequireSoyNamespaces", "true",
|
|
"--compileTimeGlobalsFile", "${resourcesSourceDir}/google/registry/ui/globals.txt"
|
|
if (deps != "") {
|
|
args "--deps", "${deps.join(',')}"
|
|
}
|
|
}
|
|
}
|
|
|
|
doLast {
|
|
def rootSoyFiles =
|
|
fileTree(
|
|
dir: "${rootSoyDirectory}",
|
|
include: ['*.soy'])
|
|
|
|
soyToJS("${outputSoyDirectory}", rootSoyFiles, "")
|
|
soyToJS("${outputSoyDirectory}/registrar",
|
|
files {
|
|
file("${rootSoyDirectory}/registrar").listFiles()
|
|
}.filter {
|
|
it.name.endsWith(".soy")
|
|
}, rootSoyFiles)
|
|
}
|
|
}
|
|
|
|
task stylesheetsToJavascript {
|
|
def cssSourceDir = "${jsDir}/google/registry/ui/css"
|
|
def outputDir = "${resourcesDir}/google/registry/ui/css"
|
|
inputs.dir cssSourceDir
|
|
outputs.dir outputDir
|
|
|
|
ext.cssCompile = { outputName, debug, cssFiles ->
|
|
javaexec {
|
|
main = "com.google.common.css.compiler.commandline.ClosureCommandLineCompiler"
|
|
classpath configurations.css
|
|
|
|
def argsBuffer = [
|
|
"--output-file", "${outputName}.css",
|
|
"--output-source-map", "${outputName}.css.map",
|
|
"--input-orientation", "LTR",
|
|
"--output-orientation", "NOCHANGE",
|
|
"--output-renaming-map", "${outputName}.css.js",
|
|
"--output-renaming-map-format", "CLOSURE_COMPILED_SPLIT_HYPHENS"
|
|
]
|
|
if (debug) {
|
|
argsBuffer.addAll(["--rename", "DEBUG", "--pretty-print"])
|
|
} else {
|
|
argsBuffer.addAll(["--rename", "CLOSURE"])
|
|
}
|
|
|
|
argsBuffer.addAll(cssFiles)
|
|
args argsBuffer
|
|
}
|
|
}
|
|
|
|
doLast {
|
|
file("${outputDir}").mkdirs()
|
|
def ignoredFiles = ["demo_css.css", "registrar_imports_raw.css"]
|
|
def sourceFiles = []
|
|
// include all CSS files that we find except for the ones explicitly ignored
|
|
fileTree(cssSourceDir).each {
|
|
if (it.name.endsWith(".css") && !ignoredFiles.contains(it.name)) {
|
|
sourceFiles << (cssSourceDir + "/" + it.name)
|
|
}
|
|
}
|
|
|
|
// The css files have to be passed to the compiler in alphabetic order to
|
|
// avoid some flaky style issues
|
|
sourceFiles.sort()
|
|
|
|
cssCompile("${outputDir}/registrar_bin", false, sourceFiles)
|
|
cssCompile("${outputDir}/registrar_dbg", true, sourceFiles)
|
|
}
|
|
}
|
|
|
|
task compileProdJS(type: JavaExec) {
|
|
def outputDir = "${resourcesDir}/google/registry/ui"
|
|
def nodeModulesDir = "${rootDir}/node_modules"
|
|
def cssSourceDir = "${resourcesDir}/google/registry/ui/css"
|
|
def jsSourceDir = "${jsDir}/google/registry/ui/js"
|
|
def externsDir = "${jsDir}/google/registry/ui/externs"
|
|
def soySourceDir = "${generatedDir}/google/registry/ui/soy"
|
|
|
|
[nodeModulesDir, cssSourceDir, jsSourceDir, externsDir, soySourceDir].each {
|
|
inputs.dir "${it}"
|
|
}
|
|
outputs.dir outputDir
|
|
|
|
classpath configurations.closureCompiler
|
|
main = 'com.google.javascript.jscomp.CommandLineRunner'
|
|
|
|
def closureArgs = []
|
|
closureArgs << "--js_output_file=${outputDir}/registrar_bin.js"
|
|
// sourcemap-related configuration
|
|
closureArgs << "--create_source_map=${outputDir}/registrar_bin.js.map"
|
|
closureArgs << "--source_map_include_content=true"
|
|
closureArgs << "--source_map_location_mapping=${rootDir}/|"
|
|
closureArgs << "--output_wrapper=\"%output% //# sourceMappingURL=registrar_bin.js.map\""
|
|
|
|
// compilation options
|
|
closureArgs << "--compilation_level=ADVANCED"
|
|
closureArgs << "--entry_point=goog:registry.registrar.main"
|
|
closureArgs << "--generate_exports"
|
|
|
|
// manually include all the required js files
|
|
closureArgs << "--js=${nodeModulesDir}/google-closure-library/**.js"
|
|
closureArgs << "--js=${jsDir}/soyutils_usegoog.js"
|
|
closureArgs << "--js=${cssSourceDir}/registrar_bin.css.js"
|
|
closureArgs << "--js=${jsSourceDir}/**.js"
|
|
// TODO(shicong) Verify the compiled JS file works in Alpha
|
|
closureArgs << "--js=${externsDir}/json.js"
|
|
closureArgs << "--js=${soySourceDir}/**.js"
|
|
args closureArgs
|
|
}
|
|
|
|
compileJava.dependsOn jaxbToJava
|
|
compileJava.dependsOn soyToJava
|
|
// The Closure JS compiler does not support Windows. It is fine to disable it if
|
|
// all we want to do is to complile the Java code on Windows.
|
|
if (!System.properties['os.name'].toLowerCase().contains('windows')) {
|
|
compileJava.dependsOn compileProdJS
|
|
assemble.dependsOn compileProdJS
|
|
}
|
|
|
|
// stylesheetsToJavascript must happen after processResources, which wipes the
|
|
// resources folder before copying data into it.
|
|
stylesheetsToJavascript.dependsOn processResources
|
|
classes.dependsOn stylesheetsToJavascript
|
|
compileProdJS.dependsOn stylesheetsToJavascript
|
|
compileProdJS.dependsOn rootProject.npmInstall
|
|
compileProdJS.dependsOn processResources
|
|
compileProdJS.dependsOn processTestResources
|
|
compileProdJS.dependsOn soyToJS
|
|
|
|
task karmaTest(type: Exec) {
|
|
dependsOn ':npmInstall'
|
|
workingDir rootProject.projectDir
|
|
executable 'node_modules/karma/bin/karma'
|
|
args('start', "${project.projectDir}/karma.conf.js")
|
|
}
|
|
|
|
test.dependsOn karmaTest
|
|
|
|
// Make testing artifacts available to be depended up on by other projects.
|
|
// TODO: factor out google.registry.testing to be a separate project.
|
|
task testJar(type: Jar) {
|
|
classifier = 'test'
|
|
from sourceSets.test.output
|
|
}
|
|
|
|
artifacts {
|
|
testRuntime testJar
|
|
}
|
|
|
|
/**
|
|
* We have to break out the test suites because some of the tests conflict
|
|
* with one another, but unfortunately this breaks the "--tests" flag. The
|
|
* --tests flag only applies to the task named on the command line (usually
|
|
* just "test"), not for all tasks of type "Test".
|
|
*
|
|
* As a better solution, FilteringTest sets testNameIncludePatterns (the
|
|
* internal property that --tests sets) from the value of the "testFilter"
|
|
* property, allowing us to filter across all the tests in core without
|
|
* explicitly specifying a test task or causing errors because there are no
|
|
* matching tests in the main task.
|
|
*
|
|
* To use it, define "testFilter" to be a comma-separated collection of class
|
|
* names (wildcards are allowed):
|
|
*
|
|
* ./gradlew test -P testFilter=*.FooBar,google.registry.tools.ShellCommandTest
|
|
*/
|
|
class FilteringTest extends Test {
|
|
|
|
private void applyTestFilter() {
|
|
if (project.testFilter) {
|
|
testNameIncludePatterns = project.testFilter.split(',')
|
|
|
|
// By default, gradle test tasks will produce a failure if no tests
|
|
// match the include/exclude/filter rules. Since test filtering allows us
|
|
// to select a set of tests from a particular task, we don't want this
|
|
// behavior.
|
|
filter.failOnNoMatchingTests = false
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set to false if you also want to include TestCase and TestSuite classes.
|
|
*
|
|
* <p>Must be defined before "test", if at all.
|
|
*/
|
|
boolean excludeTestCases = true
|
|
|
|
void setTests(List<String> tests) {
|
|
// Common exclude pattern. See README in parent directory for explanation.
|
|
if (excludeTestCases) {
|
|
exclude "**/*TestCase.*", "**/*TestSuite.*"
|
|
}
|
|
include tests
|
|
applyTestFilter()
|
|
}
|
|
|
|
/**
|
|
* Include all of the tests (except Test{Case,TestSuite}). This actually
|
|
* doesn't explicitly "include" anything, in which cast the Test class tries
|
|
* to include everything that is not explicitly excluded.
|
|
*/
|
|
void includeAllTests() {
|
|
exclude "**/*TestCase.*", "**/*TestSuite.*"
|
|
applyTestFilter()
|
|
}
|
|
}
|
|
|
|
task fragileTest(type: FilteringTest) {
|
|
// Common exclude pattern. See README in parent directory for explanation.
|
|
tests = fragileTestPatterns
|
|
|
|
if (rootProject.findProperty("skipDockerIncompatibleTests") == "true") {
|
|
exclude dockerIncompatibleTestPatterns
|
|
}
|
|
|
|
// Run every test class in a freshly started process.
|
|
forkEvery 1
|
|
}
|
|
|
|
task outcastTest(type: FilteringTest) {
|
|
tests = outcastTestPatterns
|
|
|
|
// Sets the maximum number of test executors that may exist at the same time.
|
|
maxParallelForks 5
|
|
}
|
|
|
|
// Whitebox test verifying that RegistryTool can be instantiated. Note the
|
|
// use of runtimeClasspath. This test emulates the logic in RegistryCli#run.
|
|
// A to-do is added there to refactor.
|
|
// TODO(weiminyu): Need a similar test for Registry server.
|
|
task registryToolIntegrationTest {
|
|
dependsOn compileJava
|
|
doLast {
|
|
def classLoader =
|
|
new URLClassLoader(sourceSets.main.runtimeClasspath.collect {
|
|
it.toURI().toURL()
|
|
} as URL[])
|
|
def commandClasses =
|
|
(classLoader.loadClass('google.registry.tools.RegistryTool')
|
|
.getDeclaredField('COMMAND_MAP').get(null) as Map).values()
|
|
|
|
commandClasses.each {
|
|
try {
|
|
Constructor<?> c = ((Class<?>) it).getDeclaredConstructor()
|
|
c.setAccessible(true)
|
|
c.newInstance()
|
|
} catch (Throwable e) {
|
|
throw new RuntimeException("Failed to instantiate ${it}:\n ${e}")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Dedicated test suite for schema-dependent tests.
|
|
task sqlIntegrationTest(type: FilteringTest) {
|
|
systemProperties project.getProperties().subMap('sql_schema_resource_root')
|
|
|
|
excludeTestCases = false
|
|
tests = ['google/registry/schema/integration/SqlIntegrationTestSuite.*']
|
|
}
|
|
|
|
task findGoldenImages(type: JavaExec) {
|
|
classpath = sourceSets.test.runtimeClasspath
|
|
main = 'google.registry.webdriver.GoldenImageFinder'
|
|
|
|
def arguments = []
|
|
arguments << "--screenshots_for_goldens_dir=${screenshotsForGoldensDir}"
|
|
arguments << "--new_goldens_dir=${newGoldensDir}"
|
|
arguments << "--existing_goldens_dir=${goldensDir}"
|
|
if (rootProject.findProperty("overrideExistingGoldens") == "true") {
|
|
arguments << "--override_existing_goldens=true"
|
|
}
|
|
args arguments
|
|
}
|
|
|
|
// To run the nomulus tool with these command line tokens:
|
|
// "--foo", "bar baz", "--qux=quz"
|
|
// gradle registryTool --args="--foo 'bar baz' --qux=quz"
|
|
// or:
|
|
// gradle registryTool --PtoolArgs="--foo|bar baz|--qux=quz"
|
|
// Note that the delimiting pipe can be backslash escaped if it is part of a
|
|
// parameter.
|
|
task registryTool(type: JavaExec) {
|
|
classpath = sourceSets.main.runtimeClasspath
|
|
main = 'google.registry.tools.RegistryTool'
|
|
|
|
// If "-PtoolArgs=..." is present in the command line, use it to set the args,
|
|
// otherwise use the default flag, which is "--args" to set the args.
|
|
doFirst {
|
|
def toolArgs = rootProject.findProperty("toolArgs")
|
|
if (toolArgs != null) {
|
|
def delimiter = '|'
|
|
toolArgs += delimiter
|
|
def argsList = []
|
|
def currArg = ''
|
|
for (def i = 0; i < toolArgs.length(); i++) {
|
|
def currChar = toolArgs[i]
|
|
if (currChar != delimiter) {
|
|
currArg += currChar
|
|
} else if (i != 0 && toolArgs[i - 1] == '\\') {
|
|
currArg = currArg.substring(0, currArg.length() - 1) + currChar
|
|
} else {
|
|
argsList.add(currArg)
|
|
currArg = ''
|
|
}
|
|
}
|
|
args = argsList
|
|
}
|
|
}
|
|
}
|
|
|
|
task generateGoldenImages(type: FilteringTest) {
|
|
tests = ["**/webdriver/*"]
|
|
|
|
// Sets the maximum number of test executors that may exist at the same time.
|
|
maxParallelForks 5
|
|
|
|
systemProperty 'test.screenshot.dir', screenshotsForGoldensDir
|
|
systemProperty 'test.screenshot.runAllAttempts', 'true'
|
|
systemProperty 'test.screenshot.maxAttempts', '5'
|
|
|
|
doFirst {
|
|
new File(screenshotsForGoldensDir).deleteDir()
|
|
}
|
|
}
|
|
generateGoldenImages.finalizedBy(findGoldenImages)
|
|
|
|
task flowDocsTool(type: JavaExec) {
|
|
systemProperty 'test.projectRoot', rootProject.projectRootDir
|
|
systemProperty 'test.resourcesDir', resourcesDir
|
|
|
|
classpath = sourceSets.main.runtimeClasspath
|
|
main = 'google.registry.documentation.FlowDocumentationTool'
|
|
|
|
def arguments = []
|
|
if (rootProject.flowDocsFile) {
|
|
arguments << "--output_file=${rootProject.flowDocsFile}"
|
|
} else {
|
|
arguments << "--output_file=${rootProject.projectRootDir}/docs/flows.md"
|
|
}
|
|
args arguments
|
|
}
|
|
|
|
task standardTest(type: FilteringTest) {
|
|
includeAllTests()
|
|
exclude fragileTestPatterns
|
|
exclude outcastTestPatterns
|
|
|
|
if (rootProject.findProperty("skipDockerIncompatibleTests") == "true") {
|
|
exclude dockerIncompatibleTestPatterns
|
|
}
|
|
|
|
// Run every test class in its own process.
|
|
// Uncomment to unblock build while troubleshooting inexplicable test errors.
|
|
// This setting makes the build take 35 minutes, without it it takes about 10.
|
|
// forkEvery 1
|
|
|
|
// Sets the maximum number of test executors that may exist at the same time.
|
|
maxParallelForks 5
|
|
|
|
systemProperty 'test.projectRoot', rootProject.projectRootDir
|
|
systemProperty 'test.resourcesDir', resourcesDir
|
|
|
|
doFirst {
|
|
new File(screenshotsDir).deleteDir()
|
|
}
|
|
}
|
|
|
|
test {
|
|
// Don't run any tests from this task, all testing gets done in the
|
|
// FilteringTest tasks.
|
|
exclude "**"
|
|
}.dependsOn(fragileTest, outcastTest, standardTest, registryToolIntegrationTest)
|
|
|
|
createUberJar('nomulus', 'nomulus', 'google.registry.tools.RegistryTool')
|
|
project.nomulus.dependsOn project(':third_party').jar
|
|
|
|
// A jar with classes and resources from main sourceSet, excluding internal
|
|
// data. See comments on configurations.nomulus_test above for details.
|
|
task nomulusFossJar (type: Jar) {
|
|
archiveBaseName = 'nomulus'
|
|
archiveClassifier = 'public'
|
|
from (project.sourceSets.main.output) {
|
|
exclude 'google/registry/config/files/**'
|
|
}
|
|
from (project.sourceSets.main.output) {
|
|
include 'google/registry/config/files/default-config.yaml'
|
|
include 'google/registry/config/files/nomulus-config-unittest.yaml'
|
|
}
|
|
}
|
|
|
|
// An UberJar of registry test classes, resources and all dependencies.
|
|
// See comments on configurations.nomulus_test above for details.
|
|
// TODO(weiminyu): extract shareable code with root.ext.createUberJar
|
|
task testUberJar (
|
|
type: com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar) {
|
|
mergeServiceFiles()
|
|
archiveBaseName = 'nomulus-tests'
|
|
archiveClassifier = 'alldeps'
|
|
zip64 = true
|
|
archiveVersion = ''
|
|
configurations = [project.configurations.testRuntimeClasspath]
|
|
from project.sourceSets.test.output
|
|
// Excludes signature files that accompany some dependency jars, like
|
|
// bonuncycastle. If they are present, only classes from those signed jars are
|
|
// made available to the class loader.
|
|
// see https://discuss.gradle.org/t/signing-a-custom-gradle-plugin-thats-downloaded-by-the-build-system-from-github/1365
|
|
exclude "META-INF/*.SF", "META-INF/*.DSA", "META-INF/*.RSA"
|
|
// Exclude SQL schema, which is a test dependency.
|
|
exclude 'sql/flyway/**'
|
|
// ShadowJar includes java source files when used on sourceSets.test.output.
|
|
// They are not needed.
|
|
exclude '**/*.java'
|
|
}
|
|
|
|
artifacts {
|
|
nomulus_test nomulusFossJar
|
|
nomulus_test testUberJar
|
|
}
|
|
|
|
publishing {
|
|
repositories {
|
|
maven {
|
|
url project.publish_repo
|
|
}
|
|
}
|
|
publications {
|
|
nomulusTestsPublication(MavenPublication) {
|
|
groupId 'google.registry'
|
|
artifactId 'nomulus_test'
|
|
version project.nomulus_version
|
|
artifact nomulusFossJar
|
|
artifact testUberJar
|
|
}
|
|
}
|
|
}
|
|
|
|
task buildToolImage(dependsOn: nomulus, type: Exec) {
|
|
commandLine 'docker', 'build', '-t', 'nomulus-tool', '.'
|
|
}
|
|
|
|
task copyJsFilesForTestServer(dependsOn: assemble, type: Copy) {
|
|
// Unfortunately the test server relies on having some compiled JS/CSS
|
|
// in place, so copy it over here
|
|
from "${resourcesDir}/google/registry/ui/"
|
|
include '**/*.js'
|
|
include '**/*.css'
|
|
into "${project.projectDir}/src/main/resources/google/registry/ui/"
|
|
}
|
|
|
|
task runTestServer(dependsOn: copyJsFilesForTestServer, type: JavaExec) {
|
|
main = 'google.registry.server.RegistryTestServerMain'
|
|
classpath = sourceSets.test.runtimeClasspath
|
|
}
|
|
|
|
project.build.dependsOn buildToolImage
|
|
project.build.dependsOn ':stage'
|