ISSUE-2640: BP-43: Gradle: Run tests in :stream gradle (#2659)

* Make gradle use os specific paths in build

* ISSUE-2640: BP-43: make unit tests run with gradle.

Co-authored-by: Ali Ahmed <alahmed.se@gmail.com>
Co-authored-by: Prashant Kumar <prashantk@splunk.com>
diff --git a/build.gradle b/build.gradle
index a478817..7c5bc74 100644
--- a/build.gradle
+++ b/build.gradle
@@ -27,6 +27,10 @@
     id 'java'
 }
 
+subprojects {
+    task allDeps(type: DependencyReportTask) {}
+}
+
 allprojects {
     apply from: "$rootDir/dependencies.gradle"
 
diff --git a/circe-checksum/src/main/circe/build.gradle b/circe-checksum/src/main/circe/build.gradle
index 4679f89..5b49ba8 100644
--- a/circe-checksum/src/main/circe/build.gradle
+++ b/circe-checksum/src/main/circe/build.gradle
@@ -31,8 +31,13 @@
         compileTask.includes.from("${Jvm.current().javaHome}/include",
                                   project(':circe-checksum').generateJniHeaders.javahOutputDir)
 
-        compileTask.includes.from("${Jvm.current().javaHome}/include/linux")
-        compileTask.includes.from("${Jvm.current().javaHome}/include/darwin")
+        def osFamily = binary.targetPlatform.targetMachine.operatingSystemFamily
+
+        if (osFamily.linux) {
+            compileTask.includes.from("${Jvm.current().javaHome}/include/linux")
+        } else if (osFamily.macOs) {
+            compileTask.includes.from("${Jvm.current().javaHome}/include/darwin")
+        }
 
         compileTask.source.from fileTree(dir: "cpp", include: "**/*.cpp")
         compileTask.compilerArgs.addAll(["-msse4.2", "-mpclmul", "-O3"])
diff --git a/cpu-affinity/src/main/affinity/build.gradle b/cpu-affinity/src/main/affinity/build.gradle
index c2ed921..2e44423 100644
--- a/cpu-affinity/src/main/affinity/build.gradle
+++ b/cpu-affinity/src/main/affinity/build.gradle
@@ -28,6 +28,15 @@
         compileTask.dependsOn project(':cpu-affinity').generateJniHeaders
         compileTask.includes.from("${Jvm.current().javaHome}/include",
                                   project(':cpu-affinity').generateJniHeaders.javahOutputDir)
+
+        def osFamily = binary.targetPlatform.targetMachine.operatingSystemFamily
+
+        if (osFamily.linux) {
+            compileTask.includes.from("${Jvm.current().javaHome}/include/linux")
+        } else if (osFamily.macOs) {
+            compileTask.includes.from("${Jvm.current().javaHome}/include/darwin")
+        }
+
         compileTask.includes.from("${Jvm.current().javaHome}/include/linux")
         compileTask.includes.from("${Jvm.current().javaHome}/include/darwin")
         compileTask.source.from fileTree(dir: "cpp", include: "**/*.c")
diff --git a/dependencies.gradle b/dependencies.gradle
index 89089cc..d26090e 100644
--- a/dependencies.gradle
+++ b/dependencies.gradle
@@ -22,20 +22,27 @@
 }
 
 depVersions = [
+    arquillianCubeDocker: "1.18.2",
+    arquillianJunit: "1.6.0.Final",
     bcFips: "1.0.1",
     bouncycastle: "1.60",
-    commonsCli: "1.2",
-    commonsCodec: "1.6",
+    commonsCli: "1.4",
+    commonsCodec: "1.14",
     commonsCollections4: "4.1",
+    commonsCompress: "1.19",
     commonsConfiguration: "1.10",
     commonsIO: "2.4",
     commonsLang2: "2.6",
     commonsLang3: "3.6",
+    commonsBeanutils: "1.9.3",
     curator: "4.0.1",
+    dockerJava: "3.2.5",
     errorprone: "2.1.2",
     freebuilder: "1.14.9",
+    gradleTooling: "4.0.1",
     grpc: "1.33.0",
-    guava: "21.0",
+    groovy: "2.5.8",
+    guava: "30.1-jre",
     hamcrest: "1.3",
     httpclient: "4.5.13",
     jackson: "2.9.7",
@@ -52,6 +59,7 @@
     lombok: "1.18.10",
     lz4: "1.3.0",
     mockito: "3.0.0",
+    metrics_core: "4.1.13",
     netty: "4.1.32.Final",
     nettyTcnativeBoringSsl: "2.0.20.Final",
     powermock: "2.0.2",
@@ -61,8 +69,11 @@
     slf4j: "1.7.25",
     spotbugsAnnotations: "3.1.8",
     protocGenGrpcJava: "1.12.0",
-    thrift: "0.9.3",
-    vertx: "3.4.1",
+    shrinkwrap:"3.1.4",
+    snappy: "1.1.7.7",
+    thrift: "0.12.0",
+    testcontainers: "1.14.3",
+    vertx: "3.9.2",
     yahooDatasketches: "0.8.3",
     zookeeper: "3.4.13",
 ]
@@ -72,17 +83,25 @@
     bcproveExtJdk15on: "org.bouncycastle:bcprov-ext-jdk15on:${depVersions.bouncycastle}",
     bcFips: "org.bouncycastle:bc-fips:${depVersions.bcFips}",
     commonsCli: "commons-cli:commons-cli:${depVersions.commonsCli}",
+    arquillianCubeDocker: "org.arquillian.cube:arquillian-cube-docker:${depVersions.arquillianCubeDocker}",
+    arquillianJunitContainer: "org.jboss.arquillian.junit:arquillian-junit-container:${depVersions.arquillianJunit}",
+    arquillianJunitStandalone: "org.jboss.arquillian.junit:arquillian-junit-standalone:${depVersions.arquillianJunit}",
     commonsCodec: "commons-codec:commons-codec:${depVersions.commonsCodec}",
     commonsCollections4: "org.apache.commons:commons-collections4:${depVersions.commonsCollections4}",
+    commonsCompress: "org.apache.commons:commons-compress:${depVersions.commonsCompress}",
     commonsConfiguration: "commons-configuration:commons-configuration:${depVersions.commonsConfiguration}",
     commonsIO: "commons-io:commons-io:${depVersions.commonsIO}",
     commonsLang2: "commons-lang:commons-lang:${depVersions.commonsLang2}",
     commonsLang3: "org.apache.commons:commons-lang3:${depVersions.commonsLang3}",
+    commonsBeanutils: "commons-beanutils:commons-beanutils:${depVersions.commonsBeanutils}",
     curatorFramework: "org.apache.curator:curator-framework:${depVersions.curator}",
     curatorRecipes: "org.apache.curator:curator-recipes:${depVersions.curator}",
+    dockerJava: "com.github.docker-java:docker-java:${depVersions.dockerJava}",
     errorprone: "com.google.errorprone:error_prone_annotations:${depVersions.errorprone}",
     freebuilder: "org.inferred:freebuilder:${depVersions.freebuilder}",
+    gradleTooling: "org.gradle:gradle-tooling-api:${depVersions.gradleTooling}",
     grpc: "io.grpc:grpc-all:${depVersions.grpc}",
+    groovy: "org.codehaus.groovy:groovy-all:${depVersions.groovy}",
     guava: "com.google.guava:guava:${depVersions.guava}",
     hamcrest: "org.hamcrest:hamcrest-all:${depVersions.hamcrest}",
     httpclient: "org.apache.httpcomponents:httpclient:${depVersions.httpclient}",
@@ -101,6 +120,7 @@
     log4j: "log4j:log4j:${depVersions.log4j}",
     lombok: "org.projectlombok:lombok:${depVersions.lombok}",
     lz4: "net.jpountz.lz4:lz4:${depVersions.lz4}",
+    metricsCore: "io.dropwizard.metrics:metrics-core:${depVersions.metrics_core}",
     mockito: "org.mockito:mockito-core:${depVersions.mockito}",
     nettyBuffer: "io.netty:netty-buffer:${depVersions.netty}",
     nettyCommon: "io.netty:netty-common:${depVersions.netty}",
@@ -117,9 +137,14 @@
     protoc: "com.google.protobuf:protoc:${depVersions.protobuf}",
     rocksDb: "org.rocksdb:rocksdbjni:${depVersions.rocksDb}",
     slf4j: "org.slf4j:slf4j-api:${depVersions.slf4j}",
+    slf4jSimple: "org.slf4j:slf4j-simple:${depVersions.slf4j}",
     slf4jLog4j: "org.slf4j:slf4j-log4j12:${depVersions.slf4j}",
+    shrinkwrapImpl: "org.jboss.shrinkwrap.resolver:shrinkwrap-resolver-impl-maven:${depVersions.shrinkwrap}",
+    shrinkwrapApi: "org.jboss.shrinkwrap.resolver:shrinkwrap-resolver-api:${depVersions.shrinkwrap}",
+    snappy: "org.xerial.snappy:snappy-java:${depVersions.snappy}",
     spotbugsAnnotations: "com.github.spotbugs:spotbugs-annotations:${depVersions.spotbugsAnnotations}",
     thrift: "org.apache.thrift:libthrift:${depVersions.thrift}",
+    testcontainers: "org.testcontainers:testcontainers:${depVersions.testcontainers}",
     vertxCore: "io.vertx:vertx-core:${depVersions.vertx}",
     vertxWeb: "io.vertx:vertx-web:${depVersions.vertx}",
     yahooDatasketches: "com.yahoo.datasketches:sketches-core:${depVersions.yahooDatasketches}",
diff --git a/settings.gradle b/settings.gradle
index 44e76bd..64bb5f3 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -24,10 +24,23 @@
 
 rootProject.name = 'bookkeeper'
 
-include('circe-checksum', 'circe-checksum:src:main:circe',
-        'cpu-affinity', 'cpu-affinity:src:main:affinity', 'bookkeeper-common',
-        'bookkeeper-http:http-server', 'bookkeeper-server',
-        'bookkeeper-common-allocator', 'bookkeeper-proto', 'bookkeeper-stats',
+include('circe-checksum',
+        'circe-checksum:src:main:circe',
+        'cpu-affinity',
+        'cpu-affinity:src:main:affinity',
+        'bookkeeper-common',
+        'bookkeeper-http:http-server',
+        'bookkeeper-http:vertx-http-server',
+        'bookkeeper-server',
+        'bookkeeper-common-allocator',
+        'bookkeeper-proto',
+        'bookkeeper-stats',
+        'tests:integration-tests-base',
+        'tests:integration-tests-utils',
+        'tests:integration-tests-topologies',
+        'tests:integration:cluster',
+        'tests:integration:smoke',
+        'tests:integration:standalone',
         'bookkeeper-stats-providers:prometheus-metrics-provider',
         'tools:framework',
         'stream:distributedlog:common', 'stream:distributedlog:protocol', 'stream:distributedlog:core',
diff --git a/stream/clients/java/base/build.gradle b/stream/clients/java/base/build.gradle
index 8cf5fe8..1652010 100644
--- a/stream/clients/java/base/build.gradle
+++ b/stream/clients/java/base/build.gradle
@@ -34,6 +34,10 @@
     annotationProcessor depLibs.lombok
 }
 
+configurations {
+    testCompile.exclude group:'io.grpc', module: 'grpc-netty-shaded'
+}
+
 publishing {
     publications {
         maven(MavenPublication) {
diff --git a/stream/common/build.gradle b/stream/common/build.gradle
index 4b789ca..daa2b31 100644
--- a/stream/common/build.gradle
+++ b/stream/common/build.gradle
@@ -24,7 +24,7 @@
     implementation depLibs.jsr305
     implementation depLibs.lombok
     implementation depLibs.slf4j
-
+    testImplementation depLibs.mockito
     testImplementation project(':stream:tests-common')
     testImplementation project(path: ':bookkeeper-common', configuration: 'testArtifacts')
     annotationProcessor depLibs.lombok
diff --git a/stream/distributedlog/core/build.gradle b/stream/distributedlog/core/build.gradle
index 8efe8e0..7ca40df 100644
--- a/stream/distributedlog/core/build.gradle
+++ b/stream/distributedlog/core/build.gradle
@@ -16,6 +16,10 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+plugins {
+    id 'java'
+}
+
 dependencies {
     implementation project(':bookkeeper-common')
     implementation project(':bookkeeper-server')
@@ -45,6 +49,16 @@
     testAnnotationProcessor depLibs.lombok
 }
 
+test {
+    maxHeapSize = '4G'
+    forkEvery = 1
+}
+
+test.doFirst {
+    jvmArgs("-Djunit.timeout.test=600000", "-Djunit.max.retry=3",
+            "-Djava.net.preferIPv4Stack=true", "-Dio.netty.leakDetection.level=paranoid")
+}
+
 publishing {
     publications {
         maven(MavenPublication) {
diff --git a/stream/server/build.gradle b/stream/server/build.gradle
index 8fc3068..af36a7c 100644
--- a/stream/server/build.gradle
+++ b/stream/server/build.gradle
@@ -31,13 +31,14 @@
     implementation project(':stream:storage:impl')
 
     implementation depLibs.commonsConfiguration
-    implementation depLibs.commonsLang3
+    implementation depLibs.commonsLang2
     implementation depLibs.curatorFramework
     implementation depLibs.grpc
     implementation depLibs.guava
     implementation depLibs.jcommander
     implementation depLibs.lombok
     implementation depLibs.slf4j
+    testImplementation depLibs.mockito
 
     annotationProcessor depLibs.lombok
 }
diff --git a/stream/statelib/build.gradle b/stream/statelib/build.gradle
index 6f9c04f..d2d9832 100644
--- a/stream/statelib/build.gradle
+++ b/stream/statelib/build.gradle
@@ -44,6 +44,10 @@
     testImplementation depLibs.commonsIO
     testImplementation depLibs.junit
     testImplementation depLibs.mockito
+    testImplementation depLibs.metricsCore
+    testImplementation depLibs.snappy
+    testImplementation depLibs.slf4jSimple
+    runtimeOnly depLibs.commonsBeanutils
     testImplementation project(path: ':stream:distributedlog:core', configuration: 'testArtifacts')
 
     annotationProcessor depLibs.lombok
@@ -67,3 +71,8 @@
         }
     }
 }
+
+test {
+    maxHeapSize = '2G'
+    forkEvery = 1
+}
diff --git a/tests/integration-tests-topologies/build.gradle b/tests/integration-tests-topologies/build.gradle
new file mode 100644
index 0000000..a97b034
--- /dev/null
+++ b/tests/integration-tests-topologies/build.gradle
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+dependencies {
+    implementation project(':tests:integration-tests-utils')
+    implementation depLibs.testcontainers
+    implementation depLibs.junit
+    implementation depLibs.lombok
+    implementation depLibs.slf4j
+    implementation depLibs.guava
+    implementation depLibs.commonsLang2
+    annotationProcessor depLibs.lombok
+}
+
+publishing {
+    publications {
+        maven(MavenPublication) {
+            artifactId = 'integration-tests-topologies'
+        }
+    }
+}
diff --git a/tests/integration-tests-utils/build.gradle b/tests/integration-tests-utils/build.gradle
new file mode 100644
index 0000000..9940ff9
--- /dev/null
+++ b/tests/integration-tests-utils/build.gradle
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+dependencies {
+    implementation depLibs.arquillianCubeDocker
+    implementation depLibs.zookeeper
+    implementation depLibs.junit
+    implementation depLibs.lombok
+    implementation depLibs.slf4j
+    implementation depLibs.groovy
+    implementation depLibs.shrinkwrapImpl
+    implementation depLibs.shrinkwrapApi
+    implementation depLibs.dockerJava
+    annotationProcessor depLibs.lombok
+}
+
+test {
+    exclude '**/MavenClassLoaderTest.class'
+}
+
+publishing {
+    publications {
+        maven(MavenPublication) {
+            artifactId = 'integration-tests-utils'
+        }
+    }
+}
diff --git a/tests/integration/cluster/build.gradle b/tests/integration/cluster/build.gradle
new file mode 100644
index 0000000..417e6f3
--- /dev/null
+++ b/tests/integration/cluster/build.gradle
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+dependencies {
+    implementation depLibs.grpc
+    testImplementation project(path: ':bookkeeper-common', configuration: 'testArtifacts')
+    testImplementation project(':stream:api')
+    testImplementation project(':stream:storage:api')
+    testImplementation project(':stream:common')
+    testImplementation project(':stream:proto')
+    testImplementation project(':stream:storage:impl')
+    testImplementation project(':stream:clients:java:base')
+    testImplementation project(':stream:clients:java:all')
+    testImplementation project(':bookkeeper-server')
+    testImplementation project(':bookkeeper-stats')
+    testImplementation project(':tests:integration-tests-topologies')
+
+    testCompileOnly depLibs.lombok
+    testImplementation depLibs.slf4jLog4j
+    testImplementation depLibs.testcontainers
+    testImplementation depLibs.commonsConfiguration
+    testAnnotationProcessor depLibs.lombok
+}
+
+publishing {
+    publications {
+        maven(MavenPublication) {
+            artifactId = 'tests-integration-cluster'
+        }
+    }
+}
diff --git a/tests/integration/smoke/build.gradle b/tests/integration/smoke/build.gradle
new file mode 100644
index 0000000..f19a72c
--- /dev/null
+++ b/tests/integration/smoke/build.gradle
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+dependencies {
+    testImplementation project(path: ':bookkeeper-common', configuration: 'testArtifacts')
+    testImplementation project(':bookkeeper-server')
+    testImplementation project(':tests:integration-tests-utils')
+    testCompileOnly depLibs.lombok
+    testImplementation depLibs.arquillianJunitContainer
+    testImplementation depLibs.arquillianJunitStandalone
+    testImplementation depLibs.testcontainers
+    testImplementation depLibs.commonsConfiguration
+    testImplementation depLibs.arquillianCubeDocker
+    testAnnotationProcessor depLibs.lombok
+}
+
+publishing {
+    publications {
+        maven(MavenPublication) {
+            artifactId = 'tests-integration-cluster'
+        }
+    }
+}
diff --git a/tests/integration/standalone/build.gradle b/tests/integration/standalone/build.gradle
new file mode 100644
index 0000000..0058d7e
--- /dev/null
+++ b/tests/integration/standalone/build.gradle
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+dependencies {
+    testImplementation project(path: ':bookkeeper-common', configuration: 'testArtifacts')
+    testImplementation project(':bookkeeper-server')
+    testImplementation project(':tests:integration-tests-utils')
+    testImplementation project(':tests:integration-tests-topologies')
+    testCompileOnly depLibs.lombok
+    testImplementation depLibs.arquillianJunitContainer
+    testImplementation depLibs.testcontainers
+    testImplementation depLibs.commonsConfiguration
+    testImplementation depLibs.arquillianCubeDocker
+    testAnnotationProcessor depLibs.lombok
+}
+
+publishing {
+    publications {
+        maven(MavenPublication) {
+            artifactId = 'tests-integration-cluster'
+        }
+    }
+}