Skip to content

Commit 04d9eab

Browse files
ryanbogansaratvemulapalliowaiskazi19
authored
Add integration test framework (#687)
* Add integration test task that uses the OpenSearch gradle plugin Signed-off-by: Ryan Bogan <[email protected]> * Added closeTestExtension task to kill testExtension process Signed-off-by: Ryan Bogan <[email protected]> * Fix spotless Signed-off-by: Ryan Bogan <[email protected]> * Implement resolution strategy to fix dependency conflict Signed-off-by: Ryan Bogan <[email protected]> * Minor adjustment Signed-off-by: Ryan Bogan <[email protected]> * Change jackson version Signed-off-by: Ryan Bogan <[email protected]> * Change jackson dataformat version Signed-off-by: Ryan Bogan <[email protected]> * Revert jackson version change Signed-off-by: Ryan Bogan <[email protected]> * Add resolution strategy to fix jackson dependency conflict Signed-off-by: Ryan Bogan <[email protected]> * Address PR Comments Signed-off-by: Ryan Bogan <[email protected]> * Add new implementation to fix error from separate merge Signed-off-by: Ryan Bogan <[email protected]> * Address PR Comments Signed-off-by: Ryan Bogan <[email protected]> * Address PR Comments Signed-off-by: Ryan Bogan <[email protected]> * Revert minor change Signed-off-by: Ryan Bogan <[email protected]> * Address PR Comments Signed-off-by: Ryan Bogan <[email protected]> * Add reading from yaml for testExtensionCreation Signed-off-by: Ryan Bogan <[email protected]> * Spotless Signed-off-by: Ryan Bogan <[email protected]> * Minor change Signed-off-by: Ryan Bogan <[email protected]> * Debug test commit Signed-off-by: Ryan Bogan <[email protected]> * Minor changes Signed-off-by: Ryan Bogan <[email protected]> * Remove extra test class Signed-off-by: Ryan Bogan <[email protected]> * Add index Signed-off-by: Ryan Bogan <[email protected]> * Fix inadvertent change Signed-off-by: Ryan Bogan <[email protected]> * Minor change Signed-off-by: Ryan Bogan <[email protected]> * Add log4j resolution strategy Signed-off-by: Ryan Bogan <[email protected]> * Remove testing println Signed-off-by: Ryan Bogan <[email protected]> --------- Signed-off-by: Ryan Bogan <[email protected]> Co-authored-by: Sarat Vemulapalli <[email protected]> Co-authored-by: Owais Kazi <[email protected]>
1 parent eff7635 commit 04d9eab

File tree

5 files changed

+186
-16
lines changed

5 files changed

+186
-16
lines changed

DEVELOPER_GUIDE.md

+11
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
- [Publish OpenSearch SDK for Java to Maven Local](#publish-opensearch-sdk-for-java-to-maven-local)
1414
- [Perform a REST Request on the Extension](#perform-a-rest-request-on-the-extension)
1515
- [Run Tests](#run-tests)
16+
- [Launching and debugging from an IDE](#launching-and-debugging-from-an-ide)
1617
- [Submitting Changes](#submitting-changes)
1718

1819
## Introduction
@@ -221,6 +222,16 @@ Run tests :
221222
```
222223
./gradlew clean build test
223224
```
225+
226+
Run integration tests :
227+
```
228+
./gradlew clean build integTest
229+
```
230+
231+
## Launching and debugging from an IDE
232+
233+
See [Launching and debugging from an IDE in OpenSearch](https://github.com/opensearch-project/OpenSearch/blob/main/TESTING.md#launching-and-debugging-from-an-ide)
234+
224235
## Generate Artifact
225236

226237
In opensearch-sdk-java navigate to build/distributions. Look for tar ball in the form `opensearch-sdk-java-1.0.0-SNAPSHOT.tar`. If not found follow the below steps to create one:

build.gradle

+167-15
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,26 @@
1111

1212
import java.nio.file.Files
1313
import org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestFramework
14+
import org.opensearch.gradle.test.RestIntegTestTask
15+
import org.opensearch.gradle.testclusters.ExtensionsProperties
16+
17+
buildscript {
18+
ext {
19+
opensearch_version = System.getProperty("opensearch.version", "3.0.0-SNAPSHOT")
20+
isSnapshot = "true" == System.getProperty("build.snapshot", "true")
21+
buildVersionQualifier = System.getProperty("build.version_qualifier", "")
22+
}
23+
24+
repositories {
25+
mavenLocal()
26+
mavenCentral()
27+
maven { url "https://aws.oss.sonatype.org/content/repositories/snapshots" }
28+
}
29+
30+
dependencies {
31+
classpath "org.opensearch.gradle:build-tools:${opensearch_version}"
32+
}
33+
}
1434

1535
plugins {
1636
id 'java-library'
@@ -22,21 +42,51 @@ plugins {
2242
}
2343

2444

45+
apply from: 'gradle/formatting.gradle'
46+
apply plugin: 'maven-publish'
47+
apply plugin: 'java'
48+
apply plugin: 'opensearch.opensearchplugin'
49+
apply plugin: 'opensearch.testclusters'
50+
51+
opensearchplugin {
52+
name 'opensearch-sdk-java'
53+
description 'OpenSearch Software Development Kit'
54+
classname 'org.opensearch.sdk.sample.helloworld.HelloWorldExtension'
55+
}
56+
2557
ext {
2658
projectSubstitutions = [:]
2759
licenseFile = rootProject.file('LICENSE.txt')
2860
noticeFile = rootProject.file('NOTICE.txt')
2961
}
3062

63+
dependencyLicenses.enabled = false
64+
thirdPartyAudit.enabled = false
65+
loggerUsageCheck.enabled = false
66+
forbiddenApisMain.enabled = false
67+
forbiddenApisTest.enabled = false
68+
filepermissions.enabled = false
69+
forbiddenPatterns.enabled = false
70+
testingConventions.enabled = false
71+
validateNebulaPom.enabled = false
72+
73+
def _numNodes = findProperty('numNodes') as Integer ?: 1
74+
def testPort = 4500
75+
76+
allprojects {
77+
project.ext.licenseName = 'The Apache Software License, Version 2.0'
78+
project.ext.licenseUrl = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
79+
group = 'org.opensearch'
80+
version = opensearch_version.tokenize('-')[0] + '.0'
81+
if (buildVersionQualifier) {
82+
version += "-${buildVersionQualifier}"
83+
}
84+
if (isSnapshot) {
85+
version += "-SNAPSHOT"
86+
}
87+
}
3188

32-
apply plugin: 'application'
33-
apply from: 'gradle/formatting.gradle'
34-
apply plugin: 'maven-publish'
3589

36-
// Temporary to keep "gradle run" working
37-
// TODO: change this to an extension designed for testing instead of duplicating a sample
38-
// https://github.com/opensearch-project/opensearch-sdk-java/issues/175
39-
mainClassName = 'org.opensearch.sdk.sample.helloworld.HelloWorldExtension'
4090

4191

4292
group 'org.opensearch.sdk'
@@ -49,14 +99,26 @@ java {
4999

50100
publishing {
51101
publications {
52-
group = "${group}"
53-
version = "${version}"
54-
mavenJava(MavenPublication) {
55-
from components.java
56-
}
57-
sourceCompatibility = 11
58-
targetCompatibility = 11
59-
}
102+
// add license information to generated poms
103+
all {
104+
pom {
105+
name = "opensearch-sdk-java"
106+
description = "OpenSearch SDK"
107+
}
108+
pom.withXml { XmlProvider xml ->
109+
Node node = xml.asNode()
110+
node.appendNode('inceptionYear', '2022')
111+
112+
Node license = node.appendNode('licenses').appendNode('license')
113+
license.appendNode('name', project.licenseName)
114+
license.appendNode('url', project.licenseUrl)
115+
116+
Node developer = node.appendNode('developers').appendNode('developer')
117+
developer.appendNode('name', 'opensearch-sdk-java')
118+
developer.appendNode('url', 'https://github.com/opensearch-project/opensearch-sdk-java')
119+
}
120+
}
121+
}
60122

61123
repositories {
62124
maven {
@@ -89,6 +151,11 @@ dependencies {
89151
def junit5Version = "5.9.3"
90152
def junitPlatform = "1.9.3"
91153
def jaxbVersion = "2.3.1"
154+
def jakartaVersion = "2.1.1"
155+
def jakartaInjectVersion = "2.0.1"
156+
def javaxVersion = "1"
157+
def guavaFailureAccessVersion = "1.0.1"
158+
def aopallianceVersion = "1.0"
92159

93160
api("org.opensearch:opensearch:${opensearchVersion}")
94161
implementation("org.apache.logging.log4j:log4j-api:${log4jVersion}")
@@ -99,6 +166,7 @@ dependencies {
99166
api("org.opensearch.client:opensearch-java:${opensearchVersion}")
100167
implementation("org.opensearch.plugin:transport-netty4-client:${opensearchVersion}")
101168
implementation("io.netty:netty-all:${nettyVersion}")
169+
implementation("jakarta.inject:jakarta.inject-api:${jakartaInjectVersion}")
102170
testCompileOnly("junit:junit:${junit4Version}") {
103171
exclude module : 'hamcrest'
104172
exclude module : 'hamcrest-core'
@@ -108,6 +176,13 @@ dependencies {
108176
implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:${jacksonDatabindVersion}")
109177
implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:${jacksonDatabindVersion}")
110178
implementation("com.fasterxml.jackson.datatype:jackson-datatype-guava:${jacksonDatabindVersion}")
179+
implementation("com.fasterxml.jackson.core:jackson-annotations:${jacksonDatabindVersion}")
180+
181+
implementation("com.google.guava:guava:${guavaVersion}")
182+
implementation("javax.inject:javax.inject:${javaxVersion}")
183+
implementation("com.google.guava:failureaccess:${guavaFailureAccessVersion}")
184+
implementation("aopalliance:aopalliance:${aopallianceVersion}")
185+
111186
constraints {
112187
implementation("com.google.guava:guava:${guavaVersion}") {
113188
because 'versions below 30.0 have active CVE'
@@ -118,6 +193,15 @@ dependencies {
118193
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${junit5Version}")
119194
testImplementation("org.opensearch.test:framework:${opensearchVersion}")
120195
testRuntimeOnly("org.junit.platform:junit-platform-launcher:${junitPlatform}")
196+
197+
configurations.all {
198+
resolutionStrategy.force("jakarta.json:jakarta.json-api:${jakartaVersion}")
199+
resolutionStrategy.force("com.fasterxml.jackson.core:jackson-databind:${jacksonDatabindVersion}")
200+
resolutionStrategy.force("com.fasterxml.jackson.core:jackson-core:${jacksonDatabindVersion}")
201+
resolutionStrategy.force("org.apache.logging.log4j:log4j-api:${log4jVersion}")
202+
resolutionStrategy.force("org.apache.logging.log4j:log4j-core:${log4jVersion}")
203+
resolutionStrategy.force("org.apache.logging.log4j:log4j-jul:${log4jVersion}")
204+
}
121205
}
122206

123207
// this task runs the helloworld sample extension
@@ -182,3 +266,71 @@ diffCoverageReport {
182266
failOnViolation = true
183267
}
184268
}
269+
270+
task integTest(type: RestIntegTestTask) {
271+
description = "Run tests against a cluster"
272+
testClassesDirs = sourceSets.test.output.classesDirs
273+
classpath = sourceSets.test.runtimeClasspath
274+
}
275+
//tasks.named("check").configure { dependsOn(integTest) }
276+
277+
task startTestExtension(type: Exec) {
278+
commandLine 'bash', '-c', "./gradlew helloWorld &"
279+
}
280+
281+
integTest {
282+
dependsOn(startTestExtension)
283+
284+
//TODO: find a way to add permissions for the tests
285+
systemProperty 'tests.security.manager', 'false'
286+
287+
systemProperty "https", System.getProperty("https")
288+
systemProperty "user", System.getProperty("user")
289+
systemProperty "password", System.getProperty("password")
290+
291+
// The 'doFirst' delays till execution time.
292+
doFirst {
293+
// Tell the test JVM if the cluster JVM is running under a debugger so that tests can
294+
// use longer timeouts for requests.
295+
def isDebuggingCluster = getDebug() || System.getProperty("test.debug") != null
296+
systemProperty 'cluster.debug', isDebuggingCluster
297+
// Set number of nodes system property to be used in tests
298+
systemProperty 'cluster.number_of_nodes', "1"
299+
// There seems to be an issue when running multi node run or integ tasks with unicast_hosts
300+
// not being written, the waitForAllConditions ensures it's written
301+
getClusters().forEach { cluster ->
302+
cluster.waitForAllConditions()
303+
}
304+
}
305+
306+
// The --debug-jvm command-line option makes the cluster debuggable; this makes the tests debuggable
307+
if (System.getProperty("test.debug") != null) {
308+
jvmArgs '-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005'
309+
}
310+
}
311+
312+
def testExtensionYml = new org.yaml.snakeyaml.Yaml().load(new File("src/test/resources/hello-world-extension.yml").newInputStream())
313+
314+
task closeTestExtension (type: Exec) {
315+
commandLine 'bash', '-c', "kill \$(lsof -i:${testExtensionYml.port})"
316+
}
317+
318+
tasks.named("integTest").configure { finalizedBy(closeTestExtension) }
319+
320+
testClusters.integTest {
321+
extension(new ExtensionsProperties("${testExtensionYml.name}", "${testExtensionYml.uniqueId}", "${testExtensionYml.hostAddress}", "${testExtensionYml.port}", "${testExtensionYml.version}", "${testExtensionYml.opensearchVersion}", "${testExtensionYml.minimumCompatibleVersion}"))
322+
testDistribution = "ARCHIVE"
323+
// Cluster shrink exception thrown if we try to set numberOfNodes to 1, so only apply if > 1
324+
if (_numNodes > 1) numberOfNodes = _numNodes
325+
// When running integration tests it doesn't forward the --debug-jvm to the cluster anymore
326+
// i.e. we have to use a custom property to flag when we want to debug elasticsearch JVM
327+
// since we also support multi node integration tests we increase debugPort per node
328+
if (System.getProperty("opensearch.debug") != null) {
329+
def debugPort = 5005
330+
nodes.forEach { node ->
331+
node.jvmArgs("-agentlib:jdwp=transport=dt_socket,server=n,suspend=y,address=*:${debugPort}")
332+
debugPort += 1
333+
}
334+
}
335+
336+
}

src/main/resources/sample/helloworld-settings.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
extensionName: hello-world
22
hostAddress: 127.0.0.1
3-
hostPort: 4532
3+
hostPort: 4500
44
opensearchAddress: 127.0.0.1
55
opensearchPort: 9200
66
#ssl.transport.enabled: true
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
name: hello-world
2+
uniqueId: opensearch-sdk-java-1
3+
hostAddress: '127.0.0.1'
4+
port: '4500'
5+
version: '1.0'
6+
opensearchVersion: '3.0.0'
7+
minimumCompatibleVersion: '3.0.0'

0 commit comments

Comments
 (0)