diff --git a/.github/workflows/test_build_multi_platform.yml b/.github/workflows/test_build_multi_platform.yml index 0f5d2f764..801601832 100644 --- a/.github/workflows/test_build_multi_platform.yml +++ b/.github/workflows/test_build_multi_platform.yml @@ -16,7 +16,7 @@ jobs: Build-ad-windows: strategy: matrix: - java: [ 11, 17 ] + java: [ 11, 17, 21 ] name: Build and Test Anomaly Detection Plugin on Windows runs-on: windows-latest env: @@ -49,7 +49,7 @@ jobs: needs: Get-CI-Image-Tag strategy: matrix: - java: [11,17] + java: [11, 17, 21] fail-fast: false name: Build and Test Anomaly detection Plugin runs-on: ubuntu-latest @@ -89,7 +89,7 @@ jobs: Build-ad-macos: strategy: matrix: - java: [11,17,20] + java: [11,17,21] fail-fast: false name: Build and Test Anomaly detection Plugin diff --git a/.github/workflows/test_bwc.yml b/.github/workflows/test_bwc.yml index bc166633b..953f62009 100644 --- a/.github/workflows/test_bwc.yml +++ b/.github/workflows/test_bwc.yml @@ -17,7 +17,7 @@ jobs: needs: Get-CI-Image-Tag strategy: matrix: - java: [11,17] + java: [11,17,21] fail-fast: false name: Test Anomaly detection BWC diff --git a/.github/workflows/test_security.yml b/.github/workflows/test_security.yml index 5c1df108a..352d2568f 100644 --- a/.github/workflows/test_security.yml +++ b/.github/workflows/test_security.yml @@ -11,7 +11,7 @@ jobs: Build-ad: strategy: matrix: - java: [11,17] + java: [11,17,21] fail-fast: false name: Security test workflow for Anomaly Detection diff --git a/build.gradle b/build.gradle index 951d4af60..89996ce33 100644 --- a/build.gradle +++ b/build.gradle @@ -61,11 +61,10 @@ buildscript { } plugins { - id 'nebula.ospackage' version "8.3.0" apply false - id "com.diffplug.gradle.spotless" version "3.26.1" + id 'com.netflix.nebula.ospackage' version "11.5.0" + id "com.diffplug.spotless" version "6.24.0" id 'java-library' - // Gradle 7.6 support was added in test-retry 1.4.0. - id 'org.gradle.test-retry' version '1.4.1' + id 'org.gradle.test-retry' version '1.5.7' } tasks.withType(JavaCompile) { @@ -122,6 +121,9 @@ allprojects { plugins.withId('java') { sourceCompatibility = targetCompatibility = JavaVersion.VERSION_11 } + plugins.withId('jacoco') { + jacoco.toolVersion = '0.8.11' + } } ext { @@ -146,10 +148,10 @@ configurations.all { force "org.apache.httpcomponents:httpcore:${versions.httpcore}" force "commons-codec:commons-codec:${versions.commonscodec}" - force "org.mockito:mockito-core:2.25.0" - force "org.objenesis:objenesis:3.0.1" - force "net.bytebuddy:byte-buddy:1.9.15" - force "net.bytebuddy:byte-buddy-agent:1.9.15" + force "org.mockito:mockito-core:5.9.0" + force "org.objenesis:objenesis:3.3" + force "net.bytebuddy:byte-buddy:1.14.9" + force "net.bytebuddy:byte-buddy-agent:1.14.9" force "com.google.code.gson:gson:2.8.9" force "junit:junit:4.13.2" } @@ -727,8 +729,8 @@ jacocoTestCoverageVerification { jacocoTestReport { reports { - xml.enabled = true - html.enabled = true + xml.required = true + html.required = true } } @@ -773,31 +775,21 @@ dependencies { } testImplementation group: 'pl.pragmatists', name: 'JUnitParams', version: '1.1.1' - testImplementation group: 'org.mockito', name: 'mockito-core', version: '2.25.0' - testImplementation group: 'org.powermock', name: 'powermock-api-mockito2', version: '2.0.2' - testImplementation group: 'org.powermock', name: 'powermock-module-junit4', version: '2.0.2' - testImplementation group: 'org.powermock', name: 'powermock-module-junit4-common', version: '2.0.2' - testImplementation group: 'org.powermock', name: 'powermock-core', version: '2.0.2' - testImplementation group: 'org.powermock', name: 'powermock-api-support', version: '2.0.2' - testImplementation group: 'org.powermock', name: 'powermock-reflect', version: '2.0.2' - testImplementation group: 'org.objenesis', name: 'objenesis', version: '3.0.1' - testImplementation group: 'net.bytebuddy', name: 'byte-buddy', version: '1.9.15' - testImplementation group: 'net.bytebuddy', name: 'byte-buddy-agent', version: '1.9.15' + testImplementation group: 'org.mockito', name: 'mockito-core', version: '5.9.0' + testImplementation group: 'org.objenesis', name: 'objenesis', version: '3.3' + testImplementation group: 'net.bytebuddy', name: 'byte-buddy', version: '1.14.9' + testImplementation group: 'net.bytebuddy', name: 'byte-buddy-agent', version: '1.14.9' testCompileOnly 'org.apiguardian:apiguardian-api:1.1.0' - testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.2' - testImplementation 'org.junit.jupiter:junit-jupiter-params:5.7.2' - testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.7.2' - testRuntimeOnly 'org.junit.vintage:junit-vintage-engine:5.7.2' + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.2' + testImplementation 'org.junit.jupiter:junit-jupiter-params:5.8.2' + testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.8.2' + testRuntimeOnly 'org.junit.vintage:junit-vintage-engine:5.8.2' testCompileOnly 'junit:junit:4.13.2' } compileJava.options.compilerArgs << "-Xlint:-deprecation,-rawtypes,-serial,-try,-unchecked" -test { - useJUnitPlatform() -} - -apply plugin: 'nebula.ospackage' +apply plugin: 'com.netflix.nebula.ospackage' // This is afterEvaluate because the bundlePlugin ZIP task is updated afterEvaluate and changes the ZIP name to match the plugin name afterEvaluate { @@ -838,9 +830,8 @@ afterEvaluate { task renameRpm(type: Copy) { from("$buildDir/distributions") into("$buildDir/distributions") - include archiveName - rename archiveName, "${packageName}-${version}.rpm" - doLast { delete file("$buildDir/distributions/$archiveName") } + rename "$archiveFileName", "${packageName}-${archiveVersion}.rpm" + doLast { delete file("$buildDir/distributions/$archiveFileName") } } } @@ -851,9 +842,8 @@ afterEvaluate { task renameDeb(type: Copy) { from("$buildDir/distributions") into("$buildDir/distributions") - include archiveName - rename archiveName, "${packageName}-${version}.deb" - doLast { delete file("$buildDir/distributions/$archiveName") } + rename "$archiveFileName", "${packageName}-${archiveVersion}.deb" + doLast { delete file("$buildDir/distributions/$archiveFileName") } } } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 943f0cbfa..7f93135c4 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 508322917..3499ded5c 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 65dcd68d6..1aa94a426 100755 --- a/gradlew +++ b/gradlew @@ -83,10 +83,8 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -133,10 +131,13 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. @@ -144,7 +145,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -152,7 +153,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -197,11 +198,15 @@ if "$cygwin" || "$msys" ; then done fi -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ diff --git a/src/test/java/org/opensearch/ad/NodeStateManagerTests.java b/src/test/java/org/opensearch/ad/NodeStateManagerTests.java index 8e0152096..1924e7cfe 100644 --- a/src/test/java/org/opensearch/ad/NodeStateManagerTests.java +++ b/src/test/java/org/opensearch/ad/NodeStateManagerTests.java @@ -11,12 +11,12 @@ package org.opensearch.ad; -import static org.mockito.Matchers.any; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; import static org.opensearch.ad.settings.AnomalyDetectorSettings.BACKOFF_MINUTES; import static org.opensearch.ad.settings.AnomalyDetectorSettings.MAX_RETRY_FOR_UNRESPONSIVE_NODE; @@ -232,7 +232,7 @@ public void testShouldMute() { public void testMaintenanceDoNothing() { stateManager.maintenance(); - verifyZeroInteractions(clock); + verifyNoInteractions(clock); } public void testHasRunningQuery() throws IOException { diff --git a/src/test/java/org/opensearch/ad/TestHelpers.java b/src/test/java/org/opensearch/ad/TestHelpers.java index 3c3acbfcb..ea0109e68 100644 --- a/src/test/java/org/opensearch/ad/TestHelpers.java +++ b/src/test/java/org/opensearch/ad/TestHelpers.java @@ -12,14 +12,14 @@ package org.opensearch.ad; import static org.apache.http.entity.ContentType.APPLICATION_JSON; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import static org.opensearch.ad.model.AnomalyDetectorJob.ANOMALY_DETECTOR_JOB_INDEX; import static org.opensearch.cluster.node.DiscoveryNodeRole.BUILT_IN_ROLES; import static org.opensearch.core.xcontent.XContentParserUtils.ensureExpectedToken; import static org.opensearch.index.query.AbstractQueryBuilder.parseInnerQueryBuilder; import static org.opensearch.index.seqno.SequenceNumbers.UNASSIGNED_SEQ_NO; import static org.opensearch.test.OpenSearchTestCase.*; -import static org.powermock.api.mockito.PowerMockito.mock; -import static org.powermock.api.mockito.PowerMockito.when; import java.io.IOException; import java.nio.ByteBuffer; diff --git a/src/test/java/org/opensearch/ad/cluster/ADClusterEventListenerTests.java b/src/test/java/org/opensearch/ad/cluster/ADClusterEventListenerTests.java index 1a51cb9be..6f30ed118 100644 --- a/src/test/java/org/opensearch/ad/cluster/ADClusterEventListenerTests.java +++ b/src/test/java/org/opensearch/ad/cluster/ADClusterEventListenerTests.java @@ -13,7 +13,7 @@ import static java.util.Collections.emptyMap; import static java.util.Collections.emptySet; -import static org.mockito.Matchers.any; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.opensearch.cluster.node.DiscoveryNodeRole.BUILT_IN_ROLES; diff --git a/src/test/java/org/opensearch/ad/feature/FeatureManagerTests.java b/src/test/java/org/opensearch/ad/feature/FeatureManagerTests.java index a46e4b897..c8d2991ab 100644 --- a/src/test/java/org/opensearch/ad/feature/FeatureManagerTests.java +++ b/src/test/java/org/opensearch/ad/feature/FeatureManagerTests.java @@ -19,8 +19,8 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.Matchers.argThat; -import static org.mockito.Matchers.eq; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; diff --git a/src/test/java/org/opensearch/ad/feature/SearchFeatureDaoParamTests.java b/src/test/java/org/opensearch/ad/feature/SearchFeatureDaoParamTests.java index 67d706159..b9f35dc0d 100644 --- a/src/test/java/org/opensearch/ad/feature/SearchFeatureDaoParamTests.java +++ b/src/test/java/org/opensearch/ad/feature/SearchFeatureDaoParamTests.java @@ -82,13 +82,6 @@ import org.opensearch.search.aggregations.metrics.Percentile; import org.opensearch.search.builder.SearchSourceBuilder; import org.opensearch.threadpool.ThreadPool; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PowerMockIgnore; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.powermock.modules.junit4.PowerMockRunnerDelegate; - -import com.google.gson.Gson; /** * Due to https://tinyurl.com/2y265s2w, tests with and without @Parameters annotation @@ -96,10 +89,7 @@ * while SearchFeatureDaoTests do not use @Parameters. * */ -@PowerMockIgnore("javax.management.*") -@RunWith(PowerMockRunner.class) -@PowerMockRunnerDelegate(JUnitParamsRunner.class) -@PrepareForTest({ ParseUtils.class, Gson.class }) +@RunWith(JUnitParamsRunner.class) public class SearchFeatureDaoParamTests { private SearchFeatureDao searchFeatureDao; @@ -156,7 +146,6 @@ public class SearchFeatureDaoParamTests { @Before public void setup() throws Exception { MockitoAnnotations.initMocks(this); - PowerMockito.mockStatic(ParseUtils.class); interpolator = new LinearUniformInterpolator(new SingleFeatureLinearUniformInterpolator()); @@ -233,14 +222,13 @@ public void getFeaturesForPeriod_returnExpectedToListener(List aggs long start = 100L; long end = 200L; - when(ParseUtils.generateInternalFeatureQuery(eq(detector), eq(start), eq(end), eq(xContent))).thenReturn(searchSourceBuilder); when(searchResponse.getAggregations()).thenReturn(new Aggregations(aggs)); when(detector.getEnabledFeatureIds()).thenReturn(featureIds); doAnswer(invocation -> { ActionListener listener = invocation.getArgument(1); listener.onResponse(searchResponse); return null; - }).when(client).search(eq(searchRequest), any(ActionListener.class)); + }).when(client).search(any(SearchRequest.class), any(ActionListener.class)); ActionListener> listener = mock(ActionListener.class); searchFeatureDao.getFeaturesForPeriod(detector, start, end, listener); diff --git a/src/test/java/org/opensearch/ad/feature/SearchFeatureDaoTests.java b/src/test/java/org/opensearch/ad/feature/SearchFeatureDaoTests.java index a85f9cbcd..365b5064c 100644 --- a/src/test/java/org/opensearch/ad/feature/SearchFeatureDaoTests.java +++ b/src/test/java/org/opensearch/ad/feature/SearchFeatureDaoTests.java @@ -12,6 +12,7 @@ package org.opensearch.ad.feature; import static java.util.Arrays.asList; +import static java.util.Collections.emptyMap; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.AnyOf.anyOf; import static org.hamcrest.core.IsInstanceOf.instanceOf; @@ -90,6 +91,7 @@ import org.opensearch.search.aggregations.AggregatorFactories; import org.opensearch.search.aggregations.InternalAggregations; import org.opensearch.search.aggregations.bucket.MultiBucketsAggregation; +import org.opensearch.search.aggregations.metrics.InternalMax; import org.opensearch.search.aggregations.metrics.InternalMin; import org.opensearch.search.aggregations.metrics.InternalTDigestPercentiles; import org.opensearch.search.aggregations.metrics.Max; @@ -98,14 +100,7 @@ import org.opensearch.search.aggregations.metrics.Percentile; import org.opensearch.search.builder.SearchSourceBuilder; import org.opensearch.threadpool.ThreadPool; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PowerMockIgnore; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -@PowerMockIgnore("javax.management.*") -@RunWith(PowerMockRunner.class) -@PrepareForTest({ ParseUtils.class }) + public class SearchFeatureDaoTests { private SearchFeatureDao searchFeatureDao; @@ -159,8 +154,7 @@ public class SearchFeatureDaoTests { @Before public void setup() throws Exception { MockitoAnnotations.initMocks(this); - PowerMockito.mockStatic(ParseUtils.class); - + interpolator = new LinearUniformInterpolator(new SingleFeatureLinearUniformInterpolator()); ExecutorService executorService = mock(ExecutorService.class); @@ -265,7 +259,10 @@ public void getLatestDataTime_returnExpectedToListener() { return null; }).when(client).search(eq(searchRequest), any(ActionListener.class)); - when(ParseUtils.getLatestDataTime(eq(searchResponse))).thenReturn(Optional.of(epochTime)); + InternalMax maxAgg = new InternalMax(CommonName.AGG_NAME_MAX_TIME, epochTime, DocValueFormat.RAW, emptyMap()); + InternalAggregations internalAggregations = InternalAggregations.from(Collections.singletonList(maxAgg)); + when(searchResponse.getAggregations()).thenReturn(internalAggregations); + ActionListener> listener = mock(ActionListener.class); searchFeatureDao.getLatestDataTime(detector, listener); @@ -296,13 +293,12 @@ public void getFeaturesForPeriod_throwToListener_whenResponseParsingFails() thro long start = 100L; long end = 200L; - when(ParseUtils.generateInternalFeatureQuery(eq(detector), eq(start), eq(end), eq(xContent))).thenReturn(searchSourceBuilder); when(detector.getEnabledFeatureIds()).thenReturn(null); doAnswer(invocation -> { ActionListener listener = invocation.getArgument(1); listener.onResponse(searchResponse); return null; - }).when(client).search(eq(searchRequest), any(ActionListener.class)); + }).when(client).search(any(SearchRequest.class), any(ActionListener.class)); ActionListener> listener = mock(ActionListener.class); searchFeatureDao.getFeaturesForPeriod(detector, start, end, listener); @@ -316,12 +312,11 @@ public void getFeaturesForPeriod_throwToListener_whenSearchFails() throws Except long start = 100L; long end = 200L; - when(ParseUtils.generateInternalFeatureQuery(eq(detector), eq(start), eq(end), eq(xContent))).thenReturn(searchSourceBuilder); doAnswer(invocation -> { ActionListener listener = invocation.getArgument(1); listener.onFailure(new RuntimeException()); return null; - }).when(client).search(eq(searchRequest), any(ActionListener.class)); + }).when(client).search(any(SearchRequest.class), any(ActionListener.class)); ActionListener> listener = mock(ActionListener.class); searchFeatureDao.getFeaturesForPeriod(detector, start, end, listener); diff --git a/src/test/java/org/opensearch/ad/ml/CheckpointDaoTests.java b/src/test/java/org/opensearch/ad/ml/CheckpointDaoTests.java index c41b94e10..9a8874610 100644 --- a/src/test/java/org/opensearch/ad/ml/CheckpointDaoTests.java +++ b/src/test/java/org/opensearch/ad/ml/CheckpointDaoTests.java @@ -12,7 +12,7 @@ package org.opensearch.ad.ml; import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Matchers.any; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doThrow; diff --git a/src/test/java/org/opensearch/ad/ml/ModelManagerTests.java b/src/test/java/org/opensearch/ad/ml/ModelManagerTests.java index d16776fe2..e6b0e460b 100644 --- a/src/test/java/org/opensearch/ad/ml/ModelManagerTests.java +++ b/src/test/java/org/opensearch/ad/ml/ModelManagerTests.java @@ -17,7 +17,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Matchers.eq; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; diff --git a/src/test/java/org/opensearch/ad/transport/GetAnomalyDetectorActionTests.java b/src/test/java/org/opensearch/ad/transport/GetAnomalyDetectorActionTests.java index 60144c63c..3f51105dc 100644 --- a/src/test/java/org/opensearch/ad/transport/GetAnomalyDetectorActionTests.java +++ b/src/test/java/org/opensearch/ad/transport/GetAnomalyDetectorActionTests.java @@ -12,29 +12,43 @@ package org.opensearch.ad.transport; import java.io.IOException; +import java.util.Collection; +import java.util.List; import org.junit.Assert; -import org.junit.Before; import org.junit.Test; -import org.junit.runner.RunWith; import org.mockito.Mockito; +import org.opensearch.ad.AnomalyDetectorPlugin; +import org.opensearch.ad.TestHelpers; import org.opensearch.ad.model.ADTask; import org.opensearch.ad.model.AnomalyDetector; import org.opensearch.ad.model.AnomalyDetectorJob; import org.opensearch.ad.model.DetectorProfile; +import org.opensearch.ad.model.Feature; import org.opensearch.common.io.stream.BytesStreamOutput; +import org.opensearch.core.common.io.stream.NamedWriteableAwareStreamInput; +import org.opensearch.core.common.io.stream.NamedWriteableRegistry; import org.opensearch.core.common.io.stream.StreamInput; import org.opensearch.core.rest.RestStatus; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; +import org.opensearch.plugins.Plugin; +import org.opensearch.test.InternalSettingsPlugin; +import org.opensearch.test.OpenSearchSingleNodeTestCase; -@RunWith(PowerMockRunner.class) -@PrepareForTest(GetAnomalyDetectorResponse.class) -public class GetAnomalyDetectorActionTests { - @Before - public void setUp() throws Exception { +/** + * Need to extend from OpenSearchSingleNodeTestCase and override getPlugins and writeableRegistry + * for testGetResponse. Without it, we will have exception "can't read named writeable from StreamInput" + * when deserializing AnomalyDetector. + * + */ +public class GetAnomalyDetectorActionTests extends OpenSearchSingleNodeTestCase { + @Override + protected Collection> getPlugins() { + return pluginList(InternalSettingsPlugin.class, AnomalyDetectorPlugin.class); + } + @Override + protected NamedWriteableRegistry writableRegistry() { + return getInstanceFromNode(NamedWriteableRegistry.class); } @Test @@ -51,9 +65,9 @@ public void testGetRequest() throws IOException { @Test public void testGetResponse() throws Exception { BytesStreamOutput out = new BytesStreamOutput(); - AnomalyDetector detector = Mockito.mock(AnomalyDetector.class); + Feature feature = TestHelpers.randomFeature(true); + AnomalyDetector detector = TestHelpers.randomAnomalyDetector(List.of(feature)); AnomalyDetectorJob detectorJob = Mockito.mock(AnomalyDetectorJob.class); - Mockito.doNothing().when(detector).writeTo(out); GetAnomalyDetectorResponse response = new GetAnomalyDetectorResponse( 1234, "4567", @@ -71,8 +85,8 @@ public void testGetResponse() throws Exception { false ); response.writeTo(out); - StreamInput input = out.bytes().streamInput(); - PowerMockito.whenNew(AnomalyDetector.class).withAnyArguments().thenReturn(detector); + + NamedWriteableAwareStreamInput input = new NamedWriteableAwareStreamInput(out.bytes().streamInput(), writableRegistry()); GetAnomalyDetectorResponse newResponse = new GetAnomalyDetectorResponse(input); Assert.assertNotNull(newResponse); } diff --git a/src/test/java/org/opensearch/ad/transport/MultiEntityResultTests.java b/src/test/java/org/opensearch/ad/transport/MultiEntityResultTests.java index a2404f72d..7e781fb94 100644 --- a/src/test/java/org/opensearch/ad/transport/MultiEntityResultTests.java +++ b/src/test/java/org/opensearch/ad/transport/MultiEntityResultTests.java @@ -16,7 +16,7 @@ import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Matchers.argThat; +import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; diff --git a/src/test/java/org/opensearch/ad/transport/PreviewAnomalyDetectorTransportActionTests.java b/src/test/java/org/opensearch/ad/transport/PreviewAnomalyDetectorTransportActionTests.java index f10b5ea49..5a0abbd62 100644 --- a/src/test/java/org/opensearch/ad/transport/PreviewAnomalyDetectorTransportActionTests.java +++ b/src/test/java/org/opensearch/ad/transport/PreviewAnomalyDetectorTransportActionTests.java @@ -14,7 +14,6 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.anyObject; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; @@ -185,7 +184,7 @@ public void onFailure(Exception e) { ActionListener listener = responseMock.getArgument(3); listener.onResponse(TestHelpers.randomFeatures()); return null; - }).when(featureManager).getPreviewFeatures(anyObject(), anyLong(), anyLong(), any()); + }).when(featureManager).getPreviewFeatures(any(), anyLong(), anyLong(), any()); action.doExecute(task, request, previewResponse); assertTrue(inProgressLatch.await(100, TimeUnit.SECONDS)); } @@ -396,7 +395,7 @@ public void onFailure(Exception e) { ActionListener listener = responseMock.getArgument(3); listener.onResponse(TestHelpers.randomFeatures()); return null; - }).when(featureManager).getPreviewFeatures(anyObject(), anyLong(), anyLong(), any()); + }).when(featureManager).getPreviewFeatures(any(), anyLong(), anyLong(), any()); action.doExecute(task, request, previewResponse); assertTrue(inProgressLatch.await(100, TimeUnit.SECONDS)); } diff --git a/src/test/java/org/opensearch/ad/util/ThrottlerTests.java b/src/test/java/org/opensearch/ad/util/ThrottlerTests.java index ed2a6f710..63d060b28 100644 --- a/src/test/java/org/opensearch/ad/util/ThrottlerTests.java +++ b/src/test/java/org/opensearch/ad/util/ThrottlerTests.java @@ -12,7 +12,7 @@ package org.opensearch.ad.util; import static org.mockito.Mockito.mock; -import static org.powermock.api.mockito.PowerMockito.when; +import static org.mockito.Mockito.when; import java.time.Clock;