| /* |
| * 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. |
| */ |
| |
| import org.scoverage.ScoverageReport |
| import static groovy.json.JsonOutput.* |
| |
| plugins { |
| id 'eclipse' |
| id 'maven' |
| id 'org.hidetake.swagger.generator' version '2.18.1' |
| id 'org.scoverage' |
| id 'scala' |
| } |
| |
| compileTestScala.options.encoding = 'UTF-8' |
| |
| install.dependsOn ':tools:admin:install' |
| |
| project.archivesBaseName = "openwhisk-tests" |
| |
| def leanExcludes = [ |
| '**/MaxActionDurationTests*', |
| 'invokerShoot/**' |
| ] |
| |
| def projectsWithCoverage = [ |
| ':common:scala', |
| ':core:controller', |
| ':core:scheduler', |
| ':core:invoker', |
| ':tools:admin', |
| ':core:cosmosdb:cache-invalidator' |
| ] |
| |
| def systemIncludes = [ |
| "org/apache/openwhisk/core/limits/**", |
| "org/apache/openwhisk/core/admin/**", |
| "org/apache/openwhisk/core/cli/test/**", |
| "org/apache/openwhisk/core/apigw/actions/test/**", |
| "org/apache/openwhisk/core/database/test/*CacheConcurrencyTests*", |
| "org/apache/openwhisk/core/controller/test/*ControllerApiTests*", |
| "apigw/healthtests/**", |
| "ha/**", |
| "services/**", |
| "system/basic/**", |
| "system/rest/**", |
| ] |
| |
| ext.testSets = [ |
| "REQUIRE_ONLY_DB" : [ |
| "includes" : [ |
| "org/apache/openwhisk/**" |
| ], |
| "excludes" : [ |
| "org/apache/openwhisk/core/admin/**", |
| "org/apache/openwhisk/core/apigw/actions/test/**", |
| "org/apache/openwhisk/standalone/**", |
| "org/apache/openwhisk/core/cli/test/**", |
| "org/apache/openwhisk/core/limits/**", |
| "org/apache/openwhisk/core/scheduler/**", |
| "org/apache/openwhisk/common/etcd/**", |
| "**/*CacheConcurrencyTests*", |
| "**/*ControllerApiTests*", |
| "org/apache/openwhisk/testEntities/**", |
| "invokerShoot/**" |
| ] |
| ], |
| "REQUIRE_SYSTEM" : [ |
| "includes" : systemIncludes, |
| "excludes": [ |
| "system/basic/WskMultiRuntimeTests*", |
| 'invokerShoot/**' |
| ] |
| ], |
| "REQUIRE_SCHEDULER" : [ |
| "includes" : [ |
| "org/apache/openwhisk/common/etcd/**", |
| "org/apache/openwhisk/core/containerpool/v2/test/**", |
| "org/apache/openwhisk/core/scheduler/**", |
| "org/apache/openwhisk/core/service/**", |
| ] |
| ], |
| "REQUIRE_MULTI_RUNTIME" : [ |
| "includes" : [ |
| "system/basic/*MultiRuntimeTests*", |
| "system/basic/*UnicodeTests*", |
| "limits/**" |
| ] |
| ], |
| "LEAN" : [ |
| "excludes" : leanExcludes |
| ], |
| "REQUIRE_SYSTEM_BASIC" : [ |
| "includes" : [ |
| "system/basic/**" |
| ] |
| ], |
| "REQUIRE_LEAN_SYSTEM" : [ |
| "includes" : systemIncludes, |
| |
| // Tests suits below require Kafka so they are excluded for Lean System tests |
| "excludes" : [ |
| "**/*KafkaConnectorTests*", |
| "system/basic/WskMultiRuntimeTests*", |
| "invokerShoot/**" |
| ] |
| ], |
| "REQUIRE_STANDALONE" : [ |
| "includes" : [ |
| "org/apache/openwhisk/standalone/**" |
| ] |
| ] |
| ] |
| |
| testSets.each {setName, patterns -> |
| def excludes = patterns["excludes"] ?: new HashSet<>() |
| excludes.addAll(leanExcludes) |
| patterns["excludes"] = excludes |
| } |
| |
| //The value can be specified either via env variable |
| // ORG_GRADLE_PROJECT_testSetName |
| //Or via property -PtestSetName |
| if (!project.hasProperty("testSetName")) { |
| ext.testSetName = "LEAN" |
| } |
| |
| def getPattern(String name, String type) { |
| def patterns = testSets[name] |
| assert patterns : "No pattern found for $name" |
| return patterns[type] ?: [] |
| } |
| |
| def logTestSetInfo(){ |
| println "Using testSet $testSetName - ${prettyPrint(toJson(testSets[testSetName]))}" |
| } |
| |
| test { |
| // Use command line option "-D testResultsDirName=<name>" to change the default test results directory ("test-results"). |
| // Specify a path relative to the build directory or an absolute path. |
| testResultsDirName = System.getProperty('testResultsDirName', testResultsDirName) |
| |
| exclude 'invokerShoot/**' |
| } |
| |
| task testShootInvoker(type: Test) { |
| include 'invokerShoot/**' |
| } |
| |
| task testLean(type: Test) { |
| doFirst { |
| logTestSetInfo() |
| } |
| exclude getPattern(testSetName, "excludes") |
| include getPattern(testSetName, "includes") |
| } |
| |
| task testSystemBasic(type: Test) { |
| exclude getPattern("REQUIRE_SYSTEM_BASIC", "excludes") |
| include getPattern("REQUIRE_SYSTEM_BASIC", "includes") |
| } |
| |
| task testSystemKCF(type: Test) { |
| exclude getPattern("REQUIRE_SYSTEM_BASIC", "excludes") |
| include getPattern("REQUIRE_SYSTEM_BASIC", "includes") |
| |
| // KubernetesContainerFactory's logs API is not reliable and mixes stdout/stderr into a single stream |
| exclude "**/*ActivationLogsTests*" |
| |
| // These tests fail almost all the time in openwhisk-deploy-kube TravisCI. Disabling to unblock PRs. |
| exclude "**/*WskPackageTests*" |
| exclude "**/*WskSequenceTests*" |
| } |
| |
| task testUnit(type: Test) { |
| systemProperty("whisk.spi.ArtifactStoreProvider", "org.apache.openwhisk.core.database.memory.MemoryArtifactStoreProvider") |
| exclude getPattern("REQUIRE_ONLY_DB", "excludes") |
| include getPattern("REQUIRE_ONLY_DB", "includes") |
| |
| //Test below have direct dependency on CouchDB running |
| def couchDbExcludes = [ |
| "**/*NamespaceBlacklistTests*", |
| "**/*CleanUpActivationsTest*", |
| "**/*CouchDbRestClientTests*", |
| "**/*RemoveLogsTests*", |
| "**/*ReplicatorTest*", |
| "**/*CouchDBArtifactStoreTests*", |
| "invokerShoot/**" |
| ] |
| |
| exclude couchDbExcludes |
| } |
| |
| dependencies { |
| compile "org.scala-lang:scala-library:${gradle.scala.version}" |
| compile "org.apache.commons:commons-lang3:3.3.2" |
| compile "org.apache.httpcomponents:httpclient:4.5.2:tests" |
| compile "org.apache.httpcomponents:httpmime:4.3.6" |
| compile "junit:junit:4.11" |
| compile "io.rest-assured:rest-assured:4.0.0" |
| compile "org.scalatest:scalatest_${gradle.scala.depVersion}:3.0.8" |
| compile "com.typesafe.akka:akka-testkit_${gradle.scala.depVersion}:${gradle.akka.version}" |
| compile "com.google.code.gson:gson:2.3.1" |
| compile "org.scalamock:scalamock_${gradle.scala.depVersion}:4.4.0" |
| compile "com.typesafe.akka:akka-http-testkit_${gradle.scala.depVersion}:${gradle.akka_http.version}" |
| compile "com.github.java-json-tools:json-schema-validator:2.2.8" |
| compile "org.mockito:mockito-core:2.27.0" |
| compile "io.opentracing:opentracing-mock:0.31.0" |
| compile "org.apache.curator:curator-test:${gradle.curator.version}" |
| compile "com.atlassian.oai:swagger-request-validator-core:1.4.5" |
| compile "io.github.embeddedkafka:embedded-kafka_${gradle.scala.depVersion}:2.4.0" |
| compile "com.typesafe.akka:akka-stream-kafka-testkit_${gradle.scala.depVersion}:${gradle.akka_kafka.version}" |
| compile "com.typesafe.akka:akka-stream-testkit_${gradle.scala.depVersion}:${gradle.akka.version}" |
| compile "io.fabric8:kubernetes-server-mock:${gradle.kube_client.version}" |
| |
| compile "com.amazonaws:aws-java-sdk-s3:1.11.295" |
| compile "org.testcontainers:elasticsearch:1.12.3" |
| |
| compile project(':common:scala') |
| compile project(':core:controller') |
| compile project(':core:scheduler') |
| compile project(':core:invoker') |
| compile project(':core:cosmosdb:cache-invalidator') |
| compile project(':core:monitoring:user-events') |
| compile project(':tools:admin') |
| |
| swaggerCodegen 'io.swagger:swagger-codegen-cli:2.4.9' |
| } |
| |
| def keystorePath = new File(sourceSets.test.scala.outputDir, 'keystore') |
| task deleteKeystore(type: Delete) { |
| delete keystorePath |
| } |
| task createKeystore(dependsOn: deleteKeystore) { |
| doLast { |
| def propsFile = file('../whisk.properties') |
| if (propsFile.exists()) { |
| Properties props = new Properties() |
| props.load(new FileInputStream(propsFile)) |
| keystorePath.parentFile.mkdirs() |
| def cmd = ['keytool', '-import', '-alias', 'Whisk', '-noprompt', '-trustcacerts', '-file', file(props['whisk.ssl.cert']), '-keystore', keystorePath, '-storepass', 'openwhisk'] |
| cmd.execute().waitForProcessOutput(System.out, System.err) |
| } |
| } |
| } |
| |
| task buildArtifacts(type:Exec) { |
| workingDir 'dat/actions' |
| commandLine './build.sh' |
| } |
| |
| tasks.withType(Test) { |
| dependsOn createKeystore |
| dependsOn buildArtifacts |
| } |
| createKeystore.mustRunAfter(testClasses) |
| buildArtifacts.mustRunAfter(testClasses) |
| |
| gradle.projectsEvaluated { |
| task testCoverageLean(type: Test) { |
| doFirst { |
| logTestSetInfo() |
| } |
| classpath = getScoverageClasspath(project, projectsWithCoverage) |
| exclude getPattern(testSetName, "excludes") |
| include getPattern(testSetName, "includes") |
| } |
| |
| task testCoverage(type: Test) { |
| classpath = getScoverageClasspath(project, projectsWithCoverage) |
| } |
| |
| tasks.withType(ScalaCompile) { |
| configure(scalaCompileOptions.forkOptions) { |
| memoryMaximumSize = '1g' |
| } |
| } |
| |
| tasks.withType(Test) { |
| systemProperties(System.getProperties()) |
| systemProperty("whisk.server.jar", getStandaloneJarFilePath()) |
| |
| testLogging { |
| events "passed", "skipped", "failed" |
| showStandardStreams = true |
| exceptionFormat = 'full' |
| } |
| maxHeapSize = "1024m" //Gradle 5.5 defaults to 512MB which is low |
| outputs.upToDateWhen { false } // force tests to run every time |
| } |
| /** |
| * Task to generate coverage xml report. Requires the |
| * tests to be executed prior to its invocation |
| */ |
| task reportCoverage(type: ScoverageReport) { |
| def dependentTasks = [] |
| dependentTasks << copyMeasurementFiles |
| projectsWithCoverage.forEach { |
| dependentTasks << it + ':reportScoverage' |
| } |
| dependsOn(dependentTasks) |
| //Need to recreate the logic from |
| //https://github.com/scoverage/gradle-scoverage/blob/924bf49a8f981f119d0604b44a782f3f8eecb359/src/main/groovy/org/scoverage/ScoveragePlugin.groovy#L137 |
| //default tasks retrigger the tests. As ours is a multi module integration |
| //test we have to adapt the classpath and hence cannot use default reportXXXScoverage tasks |
| runner = new org.scoverage.ScoverageRunner(project.configurations.scoverage) |
| reportDir = reportTestScoverage.reportDir |
| sources = reportTestScoverage.sources |
| sourceEncoding = 'UTF-8' |
| dataDir = reportTestScoverage.dataDir |
| coverageOutputCobertura = reportTestScoverage.coverageOutputCobertura |
| coverageOutputXML = reportTestScoverage.coverageOutputXML |
| coverageOutputHTML = reportTestScoverage.coverageOutputHTML |
| coverageDebug = reportTestScoverage.coverageDebug |
| } |
| } |
| |
| task copyMeasurementFiles() { |
| doLast{ |
| Project common = project(":common:scala") |
| Project controller = project(":core:controller") |
| Project scheduler = project(":core:scheduler") |
| Project invoker = project(":core:invoker") |
| |
| Properties wskProps = loadWhiskProps() |
| String covLogsDir = wskProps.getProperty('whisk.coverage.logs.dir') |
| assert covLogsDir : "Did not find coverage logs property 'whisk.coverage.logs.dir' in whisk props" |
| |
| File covLogs = new File(covLogsDir) |
| |
| copyAndRenameMeasurementFile(covLogs, 'controller', "common", common) |
| copyAndRenameMeasurementFile(covLogs, 'controller', "controller", controller) |
| copyAndRenameMeasurementFile(covLogs, 'scheduler', "common", common) |
| copyAndRenameMeasurementFile(covLogs, 'scheduler', "scheduler", scheduler) |
| copyAndRenameMeasurementFile(covLogs, 'invoker', "common", common) |
| copyAndRenameMeasurementFile(covLogs, 'invoker', "invoker", invoker) |
| } |
| } |
| |
| |
| /** |
| * Scoverage measurement files are named like scoverage.measurements.xxx. Where xxx is thread id. While |
| * consolidating the files between container run and normal test run we need to rename the files generated by |
| * container run so that the file name becomes unique |
| */ |
| def copyAndRenameMeasurementFile(File covLogDir, String containerName, String moduleName, Project dest){ |
| File dir = new File(new File(covLogDir, containerName), moduleName) |
| if (!dir.exists()) { |
| println "Coverage logs directory ${dir.absolutePath} does not exist. Skipping measurement file collection" |
| return |
| } |
| copy{ |
| from(dir) |
| into("${dest.buildDir.absolutePath}/scoverage") |
| rename {it+".$containerName-container"} |
| } |
| } |
| |
| def loadWhiskProps(){ |
| Properties p = new Properties() |
| file('../whisk.properties').withInputStream {is -> |
| p.load(is) |
| } |
| p |
| } |
| |
| /** |
| * Prepares the classpath which refer to scoverage instrumented classes from |
| * dependent projects "before" the non instrumented classes |
| */ |
| def getScoverageClasspath(Project project, List<String> projectNames) { |
| def combinedClasspath = projectNames.inject(project.files([])) { result, name -> |
| def cp = project.project(name).sourceSets.scoverage.runtimeClasspath |
| result + cp.filter {it.name.contains('scoverage')} |
| } |
| |
| combinedClasspath + sourceSets.test.runtimeClasspath |
| } |
| |
| swaggerSources { |
| java { |
| inputFile = file("$projectDir/../core/controller/src/main/resources/apiv1swagger.json") |
| code { |
| language = 'java' |
| configFile = file('src/test/resources/swagger-config.json') |
| dependsOn validation |
| } |
| } |
| } |
| |
| task testSwaggerCodegen(type: GradleBuild) { |
| dependsOn swaggerSources.java.code |
| buildFile = "${buildDir}/swagger-code-java/build.gradle" |
| tasks = ['build'] |
| } |
| |
| def getStandaloneJarFilePath(){ |
| project(":core:standalone").jar.archivePath |
| } |