From 0aadc037efce942b4723178d096b32e4e318117e Mon Sep 17 00:00:00 2001 From: Andrzej Cichocki Date: Wed, 28 Jun 2017 09:54:09 +0100 Subject: [PATCH] Make logging available in IntelliJ between gradle clean and assemble (#929) * Enforce absence of node from client rpc smokeTest classpath --- .idea/compiler.xml | 2 + build.gradle | 6 -- client/rpc/build.gradle | 5 +- .../corda/kotlin/rpc/ValidateClasspathTest.kt | 27 +++++++++ .../corda/core/utilities/ProcessUtilities.kt | 51 ----------------- .../kotlin/net/corda/node/BootTests.kt | 2 +- settings.gradle | 1 + smoke-test-utils/build.gradle | 1 + test-common/build.gradle | 1 + .../src/main/resources/log4j2-test.xml | 0 test-utils/build.gradle | 1 + .../kotlin/net/corda/testing/RPCDriver.kt | 2 +- .../kotlin/net/corda/testing/driver/Driver.kt | 4 +- .../corda/testing/driver/ProcessUtilities.kt | 57 +++++++++++++++++++ .../net/corda/verifier/VerifierDriver.kt | 2 +- 15 files changed, 96 insertions(+), 66 deletions(-) create mode 100644 client/rpc/src/smoke-test/kotlin/net/corda/kotlin/rpc/ValidateClasspathTest.kt delete mode 100644 core/src/main/kotlin/net/corda/core/utilities/ProcessUtilities.kt create mode 100644 test-common/build.gradle rename config/test/log4j2.xml => test-common/src/main/resources/log4j2-test.xml (100%) create mode 100644 test-utils/src/main/kotlin/net/corda/testing/driver/ProcessUtilities.kt diff --git a/.idea/compiler.xml b/.idea/compiler.xml index f89d9257e9..06d18a92b6 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -79,6 +79,8 @@ + + diff --git a/build.gradle b/build.gradle index 4515bb43da..6bc81509ac 100644 --- a/build.gradle +++ b/build.gradle @@ -103,12 +103,6 @@ allprojects { sourceCompatibility = 1.8 targetCompatibility = 1.8 - // Use manual resource copying of log4j2.xml rather than source sets. - // This prevents problems in IntelliJ with regard to duplicate source roots. - processTestResources { - from file("$rootDir/config/test/log4j2.xml") - } - tasks.withType(JavaCompile) { options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation" << "-Xlint:-options" << "-parameters" } diff --git a/client/rpc/build.gradle b/client/rpc/build.gradle index b18b563b0f..7ff552073d 100644 --- a/client/rpc/build.gradle +++ b/client/rpc/build.gradle @@ -36,9 +36,6 @@ sourceSets { } processSmokeTestResources { - from(file("$rootDir/config/test/log4j2.xml")) { - rename 'log4j2\\.xml', 'log4j2-test.xml' - } from(project(':node:capsule').tasks.buildCordaJAR) { rename 'corda-(.*)', 'corda.jar' } @@ -85,4 +82,4 @@ jar { publish { name = jar.baseName -} \ No newline at end of file +} diff --git a/client/rpc/src/smoke-test/kotlin/net/corda/kotlin/rpc/ValidateClasspathTest.kt b/client/rpc/src/smoke-test/kotlin/net/corda/kotlin/rpc/ValidateClasspathTest.kt new file mode 100644 index 0000000000..ecc534ca8a --- /dev/null +++ b/client/rpc/src/smoke-test/kotlin/net/corda/kotlin/rpc/ValidateClasspathTest.kt @@ -0,0 +1,27 @@ +package net.corda.kotlin.rpc + +import net.corda.core.div +import org.junit.Test +import java.io.File +import java.nio.file.Path +import java.nio.file.Paths +import kotlin.test.assertFalse +import kotlin.test.assertTrue + +class ValidateClasspathTest { + @Test + fun `node not on classpath`() { + val paths = System.getProperty("java.class.path").split(File.pathSeparatorChar).map { Paths.get(it) } + // First find core so that if node is there, it's in the form we expect: + assertFalse(paths.filter { it.contains("core" / "build") }.isEmpty()) + assertTrue(paths.filter { it.contains("node" / "build") }.isEmpty()) + } +} + +private fun Path.contains(that: Path): Boolean { + val size = that.nameCount + (0..nameCount - size).forEach { + if (subpath(it, it + size) == that) return true + } + return false +} diff --git a/core/src/main/kotlin/net/corda/core/utilities/ProcessUtilities.kt b/core/src/main/kotlin/net/corda/core/utilities/ProcessUtilities.kt deleted file mode 100644 index d69ab38367..0000000000 --- a/core/src/main/kotlin/net/corda/core/utilities/ProcessUtilities.kt +++ /dev/null @@ -1,51 +0,0 @@ -package net.corda.core.utilities - -import java.nio.file.Path - -// TODO This doesn't belong in core and can be moved into node -object ProcessUtilities { - inline fun startJavaProcess( - arguments: List, - classpath: String = defaultClassPath, - jdwpPort: Int? = null, - extraJvmArguments: List = emptyList(), - inheritIO: Boolean = true, - errorLogPath: Path? = null, - workingDirectory: Path? = null - ): Process { - return startJavaProcess(C::class.java.name, arguments, classpath, jdwpPort, extraJvmArguments, inheritIO, errorLogPath, workingDirectory) - } - - fun startJavaProcess( - className: String, - arguments: List, - classpath: String = defaultClassPath, - jdwpPort: Int? = null, - extraJvmArguments: List = emptyList(), - inheritIO: Boolean = true, - errorLogPath: Path? = null, - workingDirectory: Path? = null - ): Process { - val separator = System.getProperty("file.separator") - val javaPath = System.getProperty("java.home") + separator + "bin" + separator + "java" - val debugPortArgument = if (jdwpPort != null) { - listOf("-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=$jdwpPort") - } else { - emptyList() - } - - val allArguments = listOf(javaPath) + - debugPortArgument + - listOf("-Xmx200m", "-XX:+UseG1GC") + - extraJvmArguments + - listOf("-cp", classpath, className) + - arguments.toList() - return ProcessBuilder(allArguments).apply { - if (errorLogPath != null) redirectError(errorLogPath.toFile()) - if (inheritIO) inheritIO() - if (workingDirectory != null) directory(workingDirectory.toFile()) - }.start() - } - - val defaultClassPath: String get() = System.getProperty("java.class.path") -} diff --git a/node/src/integration-test/kotlin/net/corda/node/BootTests.kt b/node/src/integration-test/kotlin/net/corda/node/BootTests.kt index 1bae088182..f356852b09 100644 --- a/node/src/integration-test/kotlin/net/corda/node/BootTests.kt +++ b/node/src/integration-test/kotlin/net/corda/node/BootTests.kt @@ -37,7 +37,7 @@ class BootTests { assertThat(logConfigFile).isRegularFile() driver(isDebug = true, systemProperties = mapOf("log4j.configurationFile" to logConfigFile.toString())) { val alice = startNode(ALICE.name).get() - val logFolder = alice.configuration.baseDirectory / "logs" + val logFolder = alice.configuration.baseDirectory / NodeStartup.LOGS_DIRECTORY_NAME val logFile = logFolder.toFile().listFiles { _, name -> name.endsWith(".log") }.single() // Start second Alice, should fail assertThatThrownBy { diff --git a/settings.gradle b/settings.gradle index 1e35747a78..edfef044a8 100644 --- a/settings.gradle +++ b/settings.gradle @@ -19,6 +19,7 @@ include 'experimental' include 'experimental:sandbox' include 'experimental:quasar-hook' include 'verifier' +include 'test-common' include 'test-utils' include 'smoke-test-utils' include 'tools:explorer' diff --git a/smoke-test-utils/build.gradle b/smoke-test-utils/build.gradle index dcd94fae66..0868951903 100644 --- a/smoke-test-utils/build.gradle +++ b/smoke-test-utils/build.gradle @@ -4,5 +4,6 @@ description 'Utilities needed for smoke tests in Corda' dependencies { // Smoke tests do NOT have any Node code on the classpath! + compile project(':test-common') compile project(':client:rpc') } diff --git a/test-common/build.gradle b/test-common/build.gradle new file mode 100644 index 0000000000..472fa597c3 --- /dev/null +++ b/test-common/build.gradle @@ -0,0 +1 @@ +// Nothing needed here currently. diff --git a/config/test/log4j2.xml b/test-common/src/main/resources/log4j2-test.xml similarity index 100% rename from config/test/log4j2.xml rename to test-common/src/main/resources/log4j2-test.xml diff --git a/test-utils/build.gradle b/test-utils/build.gradle index 3c5e40f6fe..6b0dc9b873 100644 --- a/test-utils/build.gradle +++ b/test-utils/build.gradle @@ -27,6 +27,7 @@ sourceSets { } dependencies { + compile project(':test-common') compile project(':finance') compile project(':core') compile project(':node') diff --git a/test-utils/src/main/kotlin/net/corda/testing/RPCDriver.kt b/test-utils/src/main/kotlin/net/corda/testing/RPCDriver.kt index 326d01fb74..f4d09c8d23 100644 --- a/test-utils/src/main/kotlin/net/corda/testing/RPCDriver.kt +++ b/test-utils/src/main/kotlin/net/corda/testing/RPCDriver.kt @@ -12,7 +12,7 @@ import net.corda.core.div import net.corda.core.map import net.corda.core.messaging.RPCOps import net.corda.core.random63BitValue -import net.corda.core.utilities.ProcessUtilities +import net.corda.testing.driver.ProcessUtilities import net.corda.node.services.RPCUserService import net.corda.node.services.messaging.ArtemisMessagingServer import net.corda.node.services.messaging.RPCServer diff --git a/test-utils/src/main/kotlin/net/corda/testing/driver/Driver.kt b/test-utils/src/main/kotlin/net/corda/testing/driver/Driver.kt index 5e77d52cbb..4667a52bef 100644 --- a/test-utils/src/main/kotlin/net/corda/testing/driver/Driver.kt +++ b/test-utils/src/main/kotlin/net/corda/testing/driver/Driver.kt @@ -792,7 +792,7 @@ class DriverDSL( "-javaagent:$quasarJarPath" val loggingLevel = if (debugPort == null) "INFO" else "DEBUG" - ProcessUtilities.startJavaProcess( + ProcessUtilities.startCordaProcess( className = "net.corda.node.Corda", // cannot directly get class for this, so just use string arguments = listOf( "--base-directory=${nodeConf.baseDirectory}", @@ -817,7 +817,7 @@ class DriverDSL( ): ListenableFuture { return executorService.submit { val className = "net.corda.webserver.WebServer" - ProcessUtilities.startJavaProcess( + ProcessUtilities.startCordaProcess( className = className, // cannot directly get class for this, so just use string arguments = listOf("--base-directory", handle.configuration.baseDirectory.toString()), jdwpPort = debugPort, diff --git a/test-utils/src/main/kotlin/net/corda/testing/driver/ProcessUtilities.kt b/test-utils/src/main/kotlin/net/corda/testing/driver/ProcessUtilities.kt new file mode 100644 index 0000000000..7ac9eedf94 --- /dev/null +++ b/test-utils/src/main/kotlin/net/corda/testing/driver/ProcessUtilities.kt @@ -0,0 +1,57 @@ +package net.corda.testing.driver + +import net.corda.core.div +import net.corda.core.exists +import java.io.File.pathSeparator +import java.nio.file.Path + +object ProcessUtilities { + inline fun startJavaProcess( + arguments: List, + jdwpPort: Int? = null + ): Process { + return startJavaProcessImpl(C::class.java.name, arguments, defaultClassPath, jdwpPort, emptyList(), null, null) + } + + fun startCordaProcess( + className: String, + arguments: List, + jdwpPort: Int?, + extraJvmArguments: List, + errorLogPath: Path?, + workingDirectory: Path? = null + ): Process { + // FIXME: Instead of hacking our classpath, use the correct classpath for className. + val classpath = defaultClassPath.split(pathSeparator).filter { !(it / "log4j2-test.xml").exists() }.joinToString(pathSeparator) + return startJavaProcessImpl(className, arguments, classpath, jdwpPort, extraJvmArguments, errorLogPath, workingDirectory) + } + + fun startJavaProcessImpl( + className: String, + arguments: List, + classpath: String, + jdwpPort: Int?, + extraJvmArguments: List, + errorLogPath: Path?, + workingDirectory: Path? + ): Process { + val command = mutableListOf().apply { + add((System.getProperty("java.home") / "bin" / "java").toString()) + (jdwpPort != null) && add("-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=$jdwpPort") + add("-Xmx200m") + add("-XX:+UseG1GC") + addAll(extraJvmArguments) + add("-cp") + add(classpath) + add(className) + addAll(arguments) + } + return ProcessBuilder(command).apply { + if (errorLogPath != null) redirectError(errorLogPath.toFile()) // FIXME: Undone by inheritIO. + inheritIO() + if (workingDirectory != null) directory(workingDirectory.toFile()) + }.start() + } + + val defaultClassPath: String get() = System.getProperty("java.class.path") +} diff --git a/verifier/src/integration-test/kotlin/net/corda/verifier/VerifierDriver.kt b/verifier/src/integration-test/kotlin/net/corda/verifier/VerifierDriver.kt index a343c3bd2c..13cdb8d6aa 100644 --- a/verifier/src/integration-test/kotlin/net/corda/verifier/VerifierDriver.kt +++ b/verifier/src/integration-test/kotlin/net/corda/verifier/VerifierDriver.kt @@ -13,7 +13,7 @@ import net.corda.core.div import net.corda.core.map import net.corda.core.random63BitValue import net.corda.core.transactions.LedgerTransaction -import net.corda.core.utilities.ProcessUtilities +import net.corda.testing.driver.ProcessUtilities import net.corda.core.utilities.loggerFor import net.corda.node.services.config.configureDevKeyAndTrustStores import net.corda.nodeapi.ArtemisMessagingComponent.Companion.NODE_USER