diff --git a/.idea/modules.xml b/.idea/modules.xml
index 049379723553..bb30ded81900 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -43,6 +43,7 @@
+
diff --git a/platform/build-scripts/groovy/org/jetbrains/intellij/build/TestingOptions.groovy b/platform/build-scripts/groovy/org/jetbrains/intellij/build/TestingOptions.groovy
index 897175707c9b..9339db332d4a 100644
--- a/platform/build-scripts/groovy/org/jetbrains/intellij/build/TestingOptions.groovy
+++ b/platform/build-scripts/groovy/org/jetbrains/intellij/build/TestingOptions.groovy
@@ -31,10 +31,17 @@ class TestingOptions {
String testGroups = System.getProperty("intellij.build.test.groups", OLD_TEST_GROUP)
/**
- * Semicolon-separated patterns for test class names which need to be executed. Wildcard '*' is supported.
+ * Semicolon-separated patterns for test class names which need to be executed. Wildcard '*' is supported. If this option is specified,
+ * {@link #testGroups} will be ignored.
*/
String testPatterns = System.getProperty("intellij.build.test.patterns", OLD_TEST_PATTERNS)
+ /**
+ * Semicolon-separated names of JUnit run configurations in the project which need to be executed. If this option is specified,
+ * {@link #testGroups} and {@link #testPatterns} will be ignored.
+ */
+ String testConfigurations = System.getProperty("intellij.build.test.configurations")
+
/**
* Specifies components from which product will be used to run tests, by default IDEA Ultimate will be used.
*/
@@ -70,7 +77,8 @@ class TestingOptions {
*/
String customJrePath = System.getProperty("intellij.build.test.jre")
- private static final String OLD_TEST_GROUP = System.getProperty("idea.test.group", "ALL_EXCLUDE_DEFINED")
+ public static final String ALL_EXCLUDE_DEFINED_GROUP = "ALL_EXCLUDE_DEFINED"
+ private static final String OLD_TEST_GROUP = System.getProperty("idea.test.group", ALL_EXCLUDE_DEFINED_GROUP)
private static final String OLD_TEST_PATTERNS = System.getProperty("idea.test.patterns")
private static final String OLD_PLATFORM_PREFIX = System.getProperty("idea.platform.prefix")
private static final int OLD_DEBUG_PORT = SystemProperties.getIntProperty("debug.port", -1)
diff --git a/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/JUnitRunConfigurationProperties.groovy b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/JUnitRunConfigurationProperties.groovy
new file mode 100644
index 000000000000..86fa6bda1c2e
--- /dev/null
+++ b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/JUnitRunConfigurationProperties.groovy
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ */
+package org.jetbrains.intellij.build.impl
+
+import com.intellij.openapi.util.io.FileUtil
+import groovy.transform.CompileDynamic
+import groovy.transform.CompileStatic
+import org.jetbrains.intellij.build.BuildMessages
+
+@CompileStatic
+class JUnitRunConfigurationProperties {
+ final String name
+ final String moduleName
+ final List testClassPatterns
+ final List vmParameters
+ final List requiredArtifacts
+
+ static JUnitRunConfigurationProperties findRunConfiguration(String projectHome, String name, BuildMessages messages) {
+ def file = new File(projectHome, ".idea/runConfigurations/${FileUtil.sanitizeFileName(name)}.xml")
+ if (!file.exists()) {
+ messages.error("Cannot find run configurations: $file doesn't exist")
+ }
+
+ loadRunConfiguration(file, messages)
+ }
+
+ @SuppressWarnings(["GrUnresolvedAccess", "GroovyAssignabilityCheck"])
+ @CompileDynamic
+ static JUnitRunConfigurationProperties loadRunConfiguration(File file, BuildMessages messages) {
+ def root = new XmlParser().parse(file)
+ def configuration = first(root.configuration)
+ if (configuration == null) {
+ messages.error("Cannot load configuration from '$file.name': 'configuration' tag is not found")
+ }
+ if (configuration.@type != "JUnit") {
+ messages.error("Cannot load configuration from '$file.name': only JUnit run configuration are supported")
+ }
+
+ String moduleName = first(configuration.module)?.@name
+ if (moduleName == null) {
+ messages.error("Cannot run configuration from '$file.name': module name is not specified")
+ }
+ Map options = configuration.option?.collectEntries { [it.@name, it.@value] }
+ def testKind = options["TEST_OBJECT"]
+ List testClassPatterns
+ if (testKind == "class") {
+ testClassPatterns = [options["MAIN_CLASS_NAME"]]
+ }
+ else if (testKind == "package") {
+ testClassPatterns = [options["PACKAGE_NAME"] + ".*"]
+ }
+ else if (testKind == "pattern") {
+ testClassPatterns = first(configuration?.patterns)?.pattern?.collect { it.@testClass }
+ }
+ else {
+ messages.error("Cannot run $file.name configuration: '${testKind}' test kind is not supported")
+ testClassPatterns = []
+ }
+
+ List requiredArtifacts =
+ first(configuration.method)?.option?.
+ find { it.@name == "BuildArtifacts" && it.@enabled == "true" }?.
+ artifact?.collect { it.@name } ?: []
+
+ def vmParameters = options["VM_PARAMETERS"].tokenize()
+ return new JUnitRunConfigurationProperties(configuration.@name, moduleName, testClassPatterns, vmParameters, requiredArtifacts)
+ }
+
+ private static T first(Collection collection) {
+ collection == null || collection.isEmpty() ? null : collection.first()
+ }
+
+ JUnitRunConfigurationProperties(String name, String moduleName, List testClassPatterns, List vmParameters, List requiredArtifacts) {
+ this.name = name
+ this.moduleName = moduleName
+ this.testClassPatterns = testClassPatterns
+ this.requiredArtifacts = requiredArtifacts
+ this.vmParameters = vmParameters
+ }
+}
diff --git a/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/TestingTasksImpl.groovy b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/TestingTasksImpl.groovy
index 1114678c694f..49ee02534aa3 100644
--- a/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/TestingTasksImpl.groovy
+++ b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/TestingTasksImpl.groovy
@@ -18,7 +18,6 @@ package org.jetbrains.intellij.build.impl
import com.intellij.execution.CommandLineWrapperUtil
import com.intellij.openapi.util.SystemInfo
import com.intellij.openapi.util.io.FileUtilRt
-import com.intellij.openapi.util.text.StringUtil
import groovy.transform.CompileDynamic
import groovy.transform.CompileStatic
import org.apache.tools.ant.AntClassLoader
@@ -32,7 +31,6 @@ import org.jetbrains.jps.util.JpsPathUtil
import java.util.function.Predicate
import java.util.jar.Manifest
-
/**
* @author nik
*/
@@ -48,16 +46,126 @@ class TestingTasksImpl extends TestingTasks {
@Override
void runTests(List additionalJvmOptions, String defaultMainModule, Predicate rootExcludeCondition) {
+ checkOptions()
+
def compilationTasks = CompilationTasks.create(context)
- if (options.mainModule != null) {
+ def runConfigurations = options.testConfigurations?.split(";")?.collect { String name ->
+ JUnitRunConfigurationProperties.findRunConfiguration(context.paths.projectHome, name, context.messages)
+ }
+ if (runConfigurations != null) {
+ compilationTasks.compileModules(["tests_bootstrap"], ["platform-build-scripts"] + runConfigurations.collect { it.moduleName })
+ compilationTasks.buildProjectArtifacts(runConfigurations.collectMany {it.requiredArtifacts})
+ }
+ else if (options.mainModule != null) {
compilationTasks.compileModules(["tests_bootstrap"], [options.mainModule, "platform-build-scripts"])
}
else {
compilationTasks.compileAllModulesAndTests()
}
+
setupTestingDependencies()
+ def remoteDebugJvmOptions = System.getProperty("teamcity.remote-debug.jvm.options")
+ if (remoteDebugJvmOptions != null) {
+ debugTests(remoteDebugJvmOptions, additionalJvmOptions, defaultMainModule, rootExcludeCondition)
+ }
+ else if (runConfigurations != null) {
+ runTestsFromRunConfigurations(additionalJvmOptions, runConfigurations)
+ }
+ else {
+ runTestsFromGroupsAndPatterns(additionalJvmOptions, defaultMainModule, rootExcludeCondition)
+ }
+ }
+
+ private void checkOptions() {
+ if (options.testConfigurations != null) {
+ if (options.testPatterns != null) {
+ context.messages.warning("'intellij.build.test.configurations' option is specified so 'intellij.build.test.patterns' will be ignored.")
+ }
+ if (options.testGroups != TestingOptions.ALL_EXCLUDE_DEFINED_GROUP) {
+ context.messages.warning("'intellij.build.test.configurations' option is specified so 'intellij.build.test.groups' will be ignored.")
+ }
+ if (options.testConfigurations != null && options.mainModule != null) {
+ context.messages.warning("'intellij.build.test.configurations' option is specified so 'intellij.build.test.main.module' will be ignored.")
+ }
+ }
+ else if (options.testPatterns != null && options.testGroups != TestingOptions.ALL_EXCLUDE_DEFINED_GROUP) {
+ context.messages.warning("'intellij.build.test.patterns' option is specified so 'intellij.build.test.groups' will be ignored.")
+ }
+ }
+
+ private void runTestsFromRunConfigurations(List additionalJvmOptions, List runConfigurations) {
+ runConfigurations.each { configuration ->
+ context.messages.block("Run '${configuration.name}' run configuration") {
+ runTestsFromRunConfiguration(configuration, additionalJvmOptions)
+ }
+ }
+ }
+
+ private void runTestsFromRunConfiguration(JUnitRunConfigurationProperties runConfigurationProperties, List additionalJvmOptions) {
+ context.messages.progress("Running '${runConfigurationProperties.name}' run configuration")
+ List filteredVmOptions = removeStandardJvmOptions(runConfigurationProperties.vmParameters)
+ runTestsProcess(runConfigurationProperties.moduleName, null, runConfigurationProperties.testClassPatterns.join(";"),
+ filteredVmOptions + additionalJvmOptions, [:], false)
+ }
+
+ private static List removeStandardJvmOptions(List vmOptions) {
+ def ignoredPrefixes = [
+ "-ea", "-XX:+HeapDumpOnOutOfMemoryError",
+ "-Xbootclasspath",
+ "-Xmx", "-Xms",
+ "-Didea.system.path=", "-Didea.config.path=", "-Didea.home.path="
+ ]
+ vmOptions.findAll { option -> ignoredPrefixes.every { !option.startsWith(it) } }
+ }
+
+ private void runTestsFromGroupsAndPatterns(List additionalJvmOptions, String defaultMainModule, Predicate rootExcludeCondition) {
+ Map additionalSystemProperties = [:]
def mainModule = options.mainModule ?: defaultMainModule
+ if (rootExcludeCondition != null) {
+ List excludedModules = context.project.modules.findAll {
+ List contentRoots = it.contentRootsList.urls
+ !contentRoots.isEmpty() && rootExcludeCondition.test(JpsPathUtil.urlToFile(contentRoots.first()))
+ }
+ List excludedRoots = excludedModules.collectMany {
+ [context.getModuleOutputPath(it), context.getModuleTestsOutputPath(it)]
+ }
+ File excludedRootsFile = new File("$context.paths.temp/excluded.classpath")
+ excludedRootsFile.text = excludedRoots.findAll { new File(it).exists() }.join('\n')
+ additionalSystemProperties["exclude.tests.roots.file"] = excludedRootsFile.absolutePath
+ }
+
+ runTestsProcess(mainModule, options.testGroups, options.testPatterns, additionalJvmOptions, additionalSystemProperties, false
+ )
+ }
+
+ private void debugTests(String remoteDebugJvmOptions, List additionalJvmOptions, String defaultMainModule, Predicate rootExcludeCondition) {
+ def testConfigurationType = System.getProperty("teamcity.remote-debug.type")
+ if (testConfigurationType != "junit") {
+ context.messages.error("Remote debugging is supported for junit run configurations only, but 'teamcity.remote-debug.type' is $testConfigurationType")
+ }
+
+ def testObject = System.getProperty("teamcity.remote-debug.junit.type")
+ def junitClass = System.getProperty("teamcity.remote-debug.junit.class")
+ if (testObject != "class") {
+ context.messages.error("Remote debugging supports debugging all test methods in a class for now, debugging isn't supported for '$testObject'")
+ }
+ if (junitClass == null) {
+ context.messages.error("Remote debugging supports debugging all test methods in a class for now, but target class isn't specified")
+ }
+ if (options.testPatterns != null) {
+ context.messages.warning("'intellij.build.test.patterns' option is ignored while debugging via TeamCity plugin")
+ }
+ if (options.testConfigurations != null) {
+ context.messages.warning("'intellij.build.test.configurations' option is ignored while debugging via TeamCity plugin")
+ }
+ def mainModule = options.mainModule ?: defaultMainModule
+ def filteredOptions = removeStandardJvmOptions(remoteDebugJvmOptions.split(";").toList())
+ runTestsProcess(mainModule, null, junitClass, filteredOptions + additionalJvmOptions, [:], true)
+ }
+
+ private void runTestsProcess(String mainModule, String testGroups, String testPatterns,
+ List additionalJvmOptions, Map additionalSystemProperties, boolean remoteDebugging) {
List testsClasspath = context.getModuleRuntimeClasspath(context.findRequiredModule(mainModule), true)
List bootstrapClasspath = context.getModuleRuntimeClasspath(context.findRequiredModule("tests_bootstrap"), false)
def classpathFile = new File("$context.paths.temp/junit.classpath")
@@ -91,35 +199,14 @@ class TestingTasksImpl extends TestingTasks {
String tempDir = System.getProperty("teamcity.build.tempDir", System.getProperty("java.io.tmpdir"))
- def remoteDebugJvmOptions = System.getProperty("teamcity.remote-debug.jvm.options")
- if (remoteDebugJvmOptions != null) {
- def testConfigurationType = System.getProperty("teamcity.remote-debug.type")
- if (testConfigurationType != "junit") {
- context.messages.error("Remote debugging is supported for junit run configurations only, but 'teamcity.remote-debug.type' is $testConfigurationType")
- }
-
- def testObject = System.getProperty("teamcity.remote-debug.junit.type")
- def junitClass = System.getProperty("teamcity.remote-debug.junit.class")
- if (testObject != "class") {
- context.messages.error("Remote debugging supports debugging all test methods in a class for now, debugging isn't supported for '$testObject'")
- }
- if (junitClass == null) {
- context.messages.error("Remote debugging supports debugging all test methods in a class for now, but target class isn't specified")
- }
- if (options.testPatterns != null) {
- context.messages.warning("'intellij.build.test.patterns' option is ignored while debugging via TeamCity plugin")
- }
- options.testPatterns = junitClass
- }
-
Map systemProperties = [
"classpath.file" : classpathFile.absolutePath,
"idea.platform.prefix" : options.platformPrefix,
"idea.home.path" : context.paths.projectHome,
"idea.config.path" : "$tempDir/config".toString(),
"idea.system.path" : "$tempDir/system".toString(),
- "intellij.build.test.patterns" : options.testPatterns,
- "intellij.build.test.groups" : options.testGroups,
+ "intellij.build.test.patterns" : testPatterns,
+ "intellij.build.test.groups" : testGroups,
"idea.performance.tests" : System.getProperty("idea.performance.tests"),
"idea.coverage.enabled.build" : System.getProperty("idea.coverage.enabled.build"),
"teamcity.buildConfName" : System.getProperty("teamcity.buildConfName"),
@@ -131,6 +218,7 @@ class TestingTasksImpl extends TestingTasks {
"file.encoding" : "UTF-8",
"io.netty.leakDetectionLevel" : "PARANOID",
] as Map
+ systemProperties.putAll(additionalSystemProperties)
(System.getProperties() as Hashtable).each { String key, String value ->
if (key.startsWith("pass.")) {
@@ -138,33 +226,12 @@ class TestingTasksImpl extends TestingTasks {
}
}
- if (rootExcludeCondition != null) {
- List excludedModules = context.project.modules.findAll {
- List contentRoots = it.contentRootsList.urls
- !contentRoots.isEmpty() && rootExcludeCondition.test(JpsPathUtil.urlToFile(contentRoots.first()))
- }
- List excludedRoots = excludedModules.collectMany {
- [context.getModuleOutputPath(it), context.getModuleTestsOutputPath(it)]
- }
- File excludedRootsFile = new File("$context.paths.temp/excluded.classpath")
- excludedRootsFile.text = excludedRoots.findAll { new File(it).exists() }.join('\n')
- systemProperties["exclude.tests.roots.file"] = excludedRootsFile.absolutePath
- }
-
boolean suspendDebugProcess = options.suspendDebugProcess
if (systemProperties["idea.performance.tests"] == "true") {
context.messages.info("Debugging disabled for performance tests")
suspendDebugProcess = false
}
- else if (remoteDebugJvmOptions != null) {
- // ignore all options from the run configuration because they may conflict with the options defined in the build script
- String jvmDebugOption = StringUtil.splitHonorQuotes(remoteDebugJvmOptions, ' ' as char).find { it.startsWith("-agentlib:jdwp=") }
- if (jvmDebugOption == null) {
- context.messages.error("Cannot extract JVM debugging options from $remoteDebugJvmOptions")
- }
-
- jvmArgs.add(jvmDebugOption)
-
+ else if (remoteDebugging) {
context.messages.info("Remote debugging via TeamCity plugin is activated.")
if (suspendDebugProcess) {
context.messages.warning("'intellij.build.test.debug.suspend' option is ignored while debugging via TeamCity plugin")
@@ -179,7 +246,7 @@ class TestingTasksImpl extends TestingTasks {
jvmArgs.add(debuggerParameter)
}
- context.messages.info("Starting ${options.testGroups != null ? "test from groups '$options.testGroups'" : "all tests"}")
+ context.messages.info("Starting ${testGroups != null ? "test from groups '${testGroups}'" : "all tests"}")
if (options.customJrePath != null) {
context.messages.info("JVM: $options.customJrePath")
}
diff --git a/platform/build-scripts/tests/platform-build-scripts-tests.iml b/platform/build-scripts/tests/platform-build-scripts-tests.iml
new file mode 100644
index 000000000000..ddb12af2d8c7
--- /dev/null
+++ b/platform/build-scripts/tests/platform-build-scripts-tests.iml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/platform/build-scripts/tests/testResources/org/jetbrains/intellij/build/runConfigurations/test_class.xml b/platform/build-scripts/tests/testResources/org/jetbrains/intellij/build/runConfigurations/test_class.xml
new file mode 100644
index 000000000000..bd86250ae070
--- /dev/null
+++ b/platform/build-scripts/tests/testResources/org/jetbrains/intellij/build/runConfigurations/test_class.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/platform/build-scripts/tests/testResources/org/jetbrains/intellij/build/runConfigurations/test_package.xml b/platform/build-scripts/tests/testResources/org/jetbrains/intellij/build/runConfigurations/test_package.xml
new file mode 100644
index 000000000000..59a633310af0
--- /dev/null
+++ b/platform/build-scripts/tests/testResources/org/jetbrains/intellij/build/runConfigurations/test_package.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/platform/build-scripts/tests/testResources/org/jetbrains/intellij/build/runConfigurations/test_pattern.xml b/platform/build-scripts/tests/testResources/org/jetbrains/intellij/build/runConfigurations/test_pattern.xml
new file mode 100644
index 000000000000..c30153749057
--- /dev/null
+++ b/platform/build-scripts/tests/testResources/org/jetbrains/intellij/build/runConfigurations/test_pattern.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/platform/build-scripts/tests/testSrc/org/jetbrains/intellij/build/JUnitRunConfigurationPropertiesTest.kt b/platform/build-scripts/tests/testSrc/org/jetbrains/intellij/build/JUnitRunConfigurationPropertiesTest.kt
new file mode 100644
index 000000000000..a9e9f5b9dc2e
--- /dev/null
+++ b/platform/build-scripts/tests/testSrc/org/jetbrains/intellij/build/JUnitRunConfigurationPropertiesTest.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ */
+package org.jetbrains.intellij.build
+
+import com.intellij.util.io.URLUtil
+import org.jetbrains.intellij.build.impl.JUnitRunConfigurationProperties
+import org.junit.Assert.assertEquals
+import org.junit.Test
+
+class JUnitRunConfigurationPropertiesTest {
+ @Test
+ fun `load test class`() {
+ val properties = loadRunConfiguration("test_class.xml")
+ assertEquals("test class", properties.name)
+ assertEquals("main-module", properties.moduleName)
+ assertEquals(listOf("com.example.test.MainTest"), properties.testClassPatterns)
+ assertEquals(listOf("-ea", "-Xmx512m"), properties.vmParameters)
+ assertEquals(listOf("artifact1", "artifact2"), properties.requiredArtifacts)
+ }
+
+ @Test
+ fun `load test package`() {
+ val properties = loadRunConfiguration("test_package.xml")
+ assertEquals("test package", properties.name)
+ assertEquals("main-module", properties.moduleName)
+ assertEquals(listOf("com.example.test.*"), properties.testClassPatterns)
+ assertEquals(listOf("-ea"), properties.vmParameters)
+ assertEquals(emptyList(), properties.requiredArtifacts)
+ }
+
+ @Test
+ fun `load test pattern`() {
+ val properties = loadRunConfiguration("test_pattern.xml")
+ assertEquals("test pattern", properties.name)
+ assertEquals("main-module", properties.moduleName)
+ assertEquals(listOf("com.example.Test", "com.example.package..*"), properties.testClassPatterns)
+ assertEquals(listOf("-ea"), properties.vmParameters)
+ assertEquals(emptyList(), properties.requiredArtifacts)
+ }
+
+ private fun loadRunConfiguration(fileName: String): JUnitRunConfigurationProperties {
+ val url = JUnitRunConfigurationPropertiesTest::class.java.getResource("runConfigurations/$fileName")
+ return JUnitRunConfigurationProperties.loadRunConfiguration(URLUtil.urlToFile(url), MockBuildMessages())
+ }
+}
\ No newline at end of file
diff --git a/platform/build-scripts/tests/testSrc/org/jetbrains/intellij/build/MockBuildMessages.kt b/platform/build-scripts/tests/testSrc/org/jetbrains/intellij/build/MockBuildMessages.kt
new file mode 100644
index 000000000000..5c8fc530a0fb
--- /dev/null
+++ b/platform/build-scripts/tests/testSrc/org/jetbrains/intellij/build/MockBuildMessages.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+ */
+package org.jetbrains.intellij.build
+
+import groovy.lang.Closure
+import junit.framework.AssertionFailedError
+
+class MockBuildMessages : BuildMessages {
+ override fun info(message: String?) {
+ }
+
+ override fun warning(message: String?) {
+ }
+
+ override fun error(message: String?) {
+ throw AssertionFailedError(message)
+ }
+
+ override fun error(message: String?, cause: Throwable?) {
+ throw AssertionFailedError(message)
+ }
+
+ override fun compilationError(compilerName: String?, message: String?) {
+ }
+
+ override fun compilationErrors(compilerName: String?, messages: MutableList?) {
+ }
+
+ override fun progress(message: String?) {
+ }
+
+ override fun block(blockName: String, body: Closure): V {
+ return body.call()
+ }
+
+ override fun artifactBuilt(relativeArtifactPath: String?) {
+ }
+
+ override fun reportStatisticValue(key: String?, value: String?) {
+ }
+
+ override fun forkForParallelTask(taskName: String?): BuildMessages {
+ throw UnsupportedOperationException()
+ }
+
+ override fun onAllForksFinished() {
+ }
+
+ override fun onForkStarted() {
+ }
+
+ override fun onForkFinished() {
+ }
+}
\ No newline at end of file