Skip to content

Fix build due to phasing off SecurityManager usage in favor of Java Agent #2657

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ buildscript {
//****************************************************************************/

plugins {
id 'eclipse'
id 'java-library'
id 'java-test-fixtures'
id 'idea'
Expand All @@ -96,7 +97,7 @@ apply plugin: 'opensearch.opensearchplugin'
apply plugin: 'opensearch.rest-test'
apply plugin: 'opensearch.pluginzip'
apply plugin: 'opensearch.repositories'

apply plugin: 'opensearch.java-agent'

def opensearch_tmp_dir = rootProject.file('build/private/opensearch_tmp').absoluteFile
opensearch_tmp_dir.mkdirs()
Expand Down
1 change: 1 addition & 0 deletions remote-index-build-client/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ plugins {
id "io.freefair.lombok"
id 'com.diffplug.spotless' version '6.25.0'
id 'opensearch.build'
id 'opensearch.java-agent'
}

repositories {
Expand Down
37 changes: 29 additions & 8 deletions src/main/java/org/opensearch/knn/jni/PlatformUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import oshi.util.platform.mac.SysctlUtil;

import java.nio.file.Files;
Expand All @@ -27,9 +28,18 @@
import java.util.stream.Stream;

public class PlatformUtils {

private static final Logger logger = LogManager.getLogger(PlatformUtils.class);

private static volatile Boolean isAVX2Supported;
private static volatile Boolean isAVX512Supported;
private static volatile Boolean isAVX512SPRSupported;

static void reset() {
isAVX2Supported = null;
isAVX512Supported = null;
isAVX512SPRSupported = null;
}

/**
* Verify if the underlying system supports AVX2 SIMD Optimization or not
* 1. If the architecture is not x86 return false.
Expand All @@ -41,22 +51,26 @@ public class PlatformUtils {
*/
public static boolean isAVX2SupportedBySystem() {
if (!Platform.isIntel() || Platform.isWindows()) {
return false;
isAVX2Supported = false;
}

if (Platform.isMac()) {
if (isAVX2Supported != null) {
return isAVX2Supported;
}

if (Platform.isMac()) {
// sysctl or system control retrieves system info and allows processes with appropriate privileges
// to set system info. This system info contains the machine dependent cpu features that are supported by it.
// On MacOS, if the underlying processor supports AVX2 instruction set, it will be listed under the "leaf7"
// subset of instructions ("sysctl -a | grep machdep.cpu.leaf7_features").
// https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/sysctl.3.html
try {
return AccessController.doPrivileged((PrivilegedExceptionAction<Boolean>) () -> {
isAVX2Supported = AccessController.doPrivileged((PrivilegedExceptionAction<Boolean>) () -> {
String flags = SysctlUtil.sysctl("machdep.cpu.leaf7_features", "empty");
return (flags.toLowerCase(Locale.ROOT)).contains("avx2");
});
} catch (Exception e) {
isAVX2Supported = false;
logger.error("[KNN] Error fetching cpu flags info. [{}]", e.getMessage(), e);
}

Expand All @@ -70,25 +84,32 @@ public static boolean isAVX2SupportedBySystem() {
// https://ark.intel.com/content/www/us/en/ark/products/199285/intel-pentium-gold-g6600-processor-4m-cache-4-20-ghz.html
String fileName = "/proc/cpuinfo";
try {
return AccessController.doPrivileged(
isAVX2Supported = AccessController.doPrivileged(
(PrivilegedExceptionAction<Boolean>) () -> (Boolean) Files.lines(Paths.get(fileName))
.filter(s -> s.startsWith("flags"))
.anyMatch(s -> StringUtils.containsIgnoreCase(s, "avx2"))
);

} catch (Exception e) {
isAVX2Supported = false;
logger.error("[KNN] Error reading file [{}]. [{}]", fileName, e.getMessage(), e);
}
}
return false;
return isAVX2Supported;
}

public static boolean isAVX512SupportedBySystem() {
return areAVX512FlagsAvailable(new String[] { "avx512f", "avx512cd", "avx512vl", "avx512dq", "avx512bw" });
if (isAVX512Supported == null) {
isAVX512Supported = areAVX512FlagsAvailable(new String[] { "avx512f", "avx512cd", "avx512vl", "avx512dq", "avx512bw" });
}
return isAVX512Supported;
}

public static boolean isAVX512SPRSupportedBySystem() {
return areAVX512FlagsAvailable(new String[] { "avx512_fp16", "avx512_bf16", "avx512_vpopcntdq" });
if (isAVX512SPRSupported == null) {
isAVX512SPRSupported = areAVX512FlagsAvailable(new String[] { "avx512_fp16", "avx512_bf16", "avx512_vpopcntdq" });
}
return isAVX512SPRSupported;
}

private static boolean areAVX512FlagsAvailable(String[] avx512) {
Expand Down
10 changes: 10 additions & 0 deletions src/main/java/org/opensearch/knn/plugin/KNNPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import org.opensearch.knn.indices.ModelCache;
import org.opensearch.knn.indices.ModelDao;
import org.opensearch.knn.indices.ModelGraveyard;
import org.opensearch.knn.jni.PlatformUtils;
import org.opensearch.knn.plugin.rest.RestClearCacheHandler;
import org.opensearch.knn.plugin.rest.RestDeleteModelHandler;
import org.opensearch.knn.plugin.rest.RestGetModelHandler;
Expand Down Expand Up @@ -117,6 +118,7 @@
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ForkJoinPool;
import java.util.function.Supplier;

import static java.util.Collections.singletonList;
Expand Down Expand Up @@ -174,6 +176,14 @@ public class KNNPlugin extends Plugin
private ClusterService clusterService;
private Supplier<RepositoriesService> repositoriesServiceSupplier;

static {
ForkJoinPool.commonPool().execute(() -> {
Copy link
Member

@cwperks cwperks Apr 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand this correctly, the reason this works is that now the call stack will only have a single ProtectionDomain because we are caching the result instead of the 4 from here. Since this is now being done statically on class load, that would mean there would only be k-NN and JDK classes on the call stack instead of this call stack (below) where the failure was occurring:

Full stack trace
2025-04-10T18:18:30.0745441Z »  	at org.opensearch.knn.jni.JNIService.initIndex(JNIService.java:50) ~[?:?]
2025-04-10T18:18:30.0747238Z »  	at org.opensearch.knn.index.codec.nativeindex.MemOptimizedNativeIndexBuildStrategy.lambda$buildAndWriteIndex$0(MemOptimizedNativeIndexBuildStrategy.java:63) ~[?:?]
2025-04-10T18:18:30.0748969Z »  	at java.base/java.security.AccessController.doPrivileged(AccessController.java:319) ~[?:?]
2025-04-10T18:18:30.0750859Z »  	at org.opensearch.knn.index.codec.nativeindex.MemOptimizedNativeIndexBuildStrategy.buildAndWriteIndex(MemOptimizedNativeIndexBuildStrategy.java:62) ~[?:?]
2025-04-10T18:18:30.0753366Z »  	at org.opensearch.knn.index.codec.nativeindex.remote.RemoteIndexBuildStrategy.buildAndWriteIndex(RemoteIndexBuildStrategy.java:152) ~[?:?]
2025-04-10T18:18:30.0755853Z »  	at org.opensearch.knn.index.codec.nativeindex.NativeIndexWriter.buildAndWriteIndex(NativeIndexWriter.java:159) ~[?:?]
2025-04-10T18:18:30.0757378Z »  	at org.opensearch.knn.index.codec.nativeindex.NativeIndexWriter.flushIndex(NativeIndexWriter.java:105) ~[?:?]
2025-04-10T18:18:30.0759129Z »  	at org.opensearch.knn.index.codec.KNN990Codec.NativeEngines990KnnVectorsWriter.flush(NativeEngines990KnnVectorsWriter.java:128) ~[?:?]
2025-04-10T18:18:30.0761709Z »  	at org.apache.lucene.codecs.perfield.PerFieldKnnVectorsFormat$FieldsWriter.flush(PerFieldKnnVectorsFormat.java:120) ~[lucene-core-10.1.0.jar:10.1.0 884954006de769dc43b811267230d625886e6515 - 2024-12-17 16:15:44]
2025-04-10T18:18:30.0764749Z »  	at org.apache.lucene.index.VectorValuesConsumer.flush(VectorValuesConsumer.java:76) ~[lucene-core-10.1.0.jar:10.1.0 884954006de769dc43b811267230d625886e6515 - 2024-12-17 16:15:44]
2025-04-10T18:18:30.0767204Z »  	at org.apache.lucene.index.IndexingChain.flush(IndexingChain.java:305) ~[lucene-core-10.1.0.jar:10.1.0 884954006de769dc43b811267230d625886e6515 - 2024-12-17 16:15:44]
2025-04-10T18:18:30.0769225Z »  	at org.apache.lucene.index.DocumentsWriterPerThread.flush(DocumentsWriterPerThread.java:456) ~[lucene-core-10.1.0.jar:10.1.0 884954006de769dc43b811267230d625886e6515 - 2024-12-17 16:15:44]
2025-04-10T18:18:30.0771702Z »  	at org.apache.lucene.index.DocumentsWriter.doFlush(DocumentsWriter.java:502) ~[lucene-core-10.1.0.jar:10.1.0 884954006de769dc43b811267230d625886e6515 - 2024-12-17 16:15:44]
2025-04-10T18:18:30.0773880Z »  	at org.apache.lucene.index.DocumentsWriter.maybeFlush(DocumentsWriter.java:456) ~[lucene-core-10.1.0.jar:10.1.0 884954006de769dc43b811267230d625886e6515 - 2024-12-17 16:15:44]
2025-04-10T18:18:30.0776468Z »  	at org.apache.lucene.index.DocumentsWriter.flushAllThreads(DocumentsWriter.java:649) ~[lucene-core-10.1.0.jar:10.1.0 884954006de769dc43b811267230d625886e6515 - 2024-12-17 16:15:44]
2025-04-10T18:18:30.0778717Z »  	at org.apache.lucene.index.IndexWriter.getReader(IndexWriter.java:578) ~[lucene-core-10.1.0.jar:10.1.0 884954006de769dc43b811267230d625886e6515 - 2024-12-17 16:15:44]
2025-04-10T18:18:30.0781115Z »  	at org.apache.lucene.index.StandardDirectoryReader.doOpenFromWriter(StandardDirectoryReader.java:382) ~[lucene-core-10.1.0.jar:10.1.0 884954006de769dc43b811267230d625886e6515 - 2024-12-17 16:15:44]
2025-04-10T18:18:30.0783673Z »  	at org.apache.lucene.index.StandardDirectoryReader.doOpenIfChanged(StandardDirectoryReader.java:356) ~[lucene-core-10.1.0.jar:10.1.0 884954006de769dc43b811267230d625886e6515 - 2024-12-17 16:15:44]
2025-04-10T18:18:30.0786557Z »  	at org.apache.lucene.index.StandardDirectoryReader.doOpenIfChanged(StandardDirectoryReader.java:346) ~[lucene-core-10.1.0.jar:10.1.0 884954006de769dc43b811267230d625886e6515 - 2024-12-17 16:15:44]
2025-04-10T18:18:30.0789243Z »  	at org.apache.lucene.index.FilterDirectoryReader.doOpenIfChanged(FilterDirectoryReader.java:112) ~[lucene-core-10.1.0.jar:10.1.0 884954006de769dc43b811267230d625886e6515 - 2024-12-17 16:15:44]
2025-04-10T18:18:30.0791886Z »  	at org.apache.lucene.index.DirectoryReader.openIfChanged(DirectoryReader.java:170) ~[lucene-core-10.1.0.jar:10.1.0 884954006de769dc43b811267230d625886e6515 - 2024-12-17 16:15:44]
2025-04-10T18:18:30.0794375Z »  	at org.opensearch.index.engine.OpenSearchReaderManager.refreshIfNeeded(OpenSearchReaderManager.java:72) ~[opensearch-3.0.0-beta1-SNAPSHOT.jar:3.0.0-beta1-SNAPSHOT]
2025-04-10T18:18:30.0796979Z »  	at org.opensearch.index.engine.OpenSearchReaderManager.refreshIfNeeded(OpenSearchReaderManager.java:52) ~[opensearch-3.0.0-beta1-SNAPSHOT.jar:3.0.0-beta1-SNAPSHOT]
2025-04-10T18:18:30.0799472Z »  	at org.apache.lucene.search.ReferenceManager.doMaybeRefresh(ReferenceManager.java:167) ~[lucene-core-10.1.0.jar:10.1.0 884954006de769dc43b811267230d625886e6515 - 2024-12-17 16:15:44]
2025-04-10T18:18:30.0802154Z »  	at org.apache.lucene.search.ReferenceManager.maybeRefreshBlocking(ReferenceManager.java:240) ~[lucene-core-10.1.0.jar:10.1.0 884954006de769dc43b811267230d625886e6515 - 2024-12-17 16:15:44]
2025-04-10T18:18:30.0804640Z »  	at org.opensearch.index.engine.InternalEngine$ExternalReaderManager.refreshIfNeeded(InternalEngine.java:443) ~[opensearch-3.0.0-beta1-SNAPSHOT.jar:3.0.0-beta1-SNAPSHOT]
2025-04-10T18:18:30.0807389Z »  	at org.opensearch.index.engine.InternalEngine$ExternalReaderManager.refreshIfNeeded(InternalEngine.java:423) ~[opensearch-3.0.0-beta1-SNAPSHOT.jar:3.0.0-beta1-SNAPSHOT]
2025-04-10T18:18:30.0809781Z »  	at org.apache.lucene.search.ReferenceManager.doMaybeRefresh(ReferenceManager.java:167) ~[lucene-core-10.1.0.jar:10.1.0 884954006de769dc43b811267230d625886e6515 - 2024-12-17 16:15:44]
2025-04-10T18:18:30.0812430Z »  	at org.apache.lucene.search.ReferenceManager.maybeRefreshBlocking(ReferenceManager.java:240) ~[lucene-core-10.1.0.jar:10.1.0 884954006de769dc43b811267230d625886e6515 - 2024-12-17 16:15:44]
2025-04-10T18:18:30.0813833Z »  	at org.opensearch.index.engine.InternalEngine.refresh(InternalEngine.java:1805) ~[opensearch-3.0.0-beta1-SNAPSHOT.jar:3.0.0-beta1-SNAPSHOT]
2025-04-10T18:18:30.0815048Z »  	at org.opensearch.index.engine.InternalEngine.refresh(InternalEngine.java:1782) ~[opensearch-3.0.0-beta1-SNAPSHOT.jar:3.0.0-beta1-SNAPSHOT]
2025-04-10T18:18:30.0816612Z »  	at org.opensearch.index.shard.IndexShard.refresh(IndexShard.java:1421) ~[opensearch-3.0.0-beta1-SNAPSHOT.jar:3.0.0-beta1-SNAPSHOT]
2025-04-10T18:18:30.0818081Z »  	at org.opensearch.action.admin.indices.refresh.TransportShardRefreshAction.lambda$shardOperationOnPrimary$0(TransportShardRefreshAction.java:101) ~[opensearch-3.0.0-beta1-SNAPSHOT.jar:3.0.0-beta1-SNAPSHOT]
2025-04-10T18:18:30.0819408Z »  	at org.opensearch.core.action.ActionListener.completeWith(ActionListener.java:344) ~[opensearch-core-3.0.0-beta1-SNAPSHOT.jar:3.0.0-beta1-SNAPSHOT]
2025-04-10T18:18:30.0820754Z »  	at org.opensearch.action.admin.indices.refresh.TransportShardRefreshAction.shardOperationOnPrimary(TransportShardRefreshAction.java:100) ~[opensearch-3.0.0-beta1-SNAPSHOT.jar:3.0.0-beta1-SNAPSHOT]
2025-04-10T18:18:30.0822317Z »  	at org.opensearch.action.admin.indices.refresh.TransportShardRefreshAction.shardOperationOnPrimary(TransportShardRefreshAction.java:57) ~[opensearch-3.0.0-beta1-SNAPSHOT.jar:3.0.0-beta1-SNAPSHOT]
2025-04-10T18:18:30.0823870Z »  	at org.opensearch.action.support.replication.TransportReplicationAction$PrimaryShardReference.perform(TransportReplicationAction.java:1333) ~[opensearch-3.0.0-beta1-SNAPSHOT.jar:3.0.0-beta1-SNAPSHOT]
2025-04-10T18:18:30.0826092Z »  	at org.opensearch.action.support.replication.ReplicationOperation.execute(ReplicationOperation.java:150) ~[opensearch-3.0.0-beta1-SNAPSHOT.jar:3.0.0-beta1-SNAPSHOT]
2025-04-10T18:18:30.0829035Z »  	at org.opensearch.action.support.replication.TransportReplicationAction$AsyncPrimaryAction.runWithPrimaryShardReference(TransportReplicationAction.java:654) ~[opensearch-3.0.0-beta1-SNAPSHOT.jar:3.0.0-beta1-SNAPSHOT]
2025-04-10T18:18:30.0831286Z »  	at org.opensearch.action.support.replication.TransportReplicationAction$AsyncPrimaryAction.lambda$doRun$0(TransportReplicationAction.java:547) ~[opensearch-3.0.0-beta1-SNAPSHOT.jar:3.0.0-beta1-SNAPSHOT]
2025-04-10T18:18:30.0832579Z »  	at org.opensearch.core.action.ActionListener$1.onResponse(ActionListener.java:82) ~[opensearch-core-3.0.0-beta1-SNAPSHOT.jar:3.0.0-beta1-SNAPSHOT]
2025-04-10T18:18:30.0834269Z »  	at org.opensearch.index.shard.IndexShard.lambda$wrapPrimaryOperationPermitListener$36(IndexShard.java:4203) ~[opensearch-3.0.0-beta1-SNAPSHOT.jar:3.0.0-beta1-SNAPSHOT]
2025-04-10T18:18:30.0836729Z »  	at org.opensearch.core.action.ActionListener$3.onResponse(ActionListener.java:132) ~[opensearch-core-3.0.0-beta1-SNAPSHOT.jar:3.0.0-beta1-SNAPSHOT]
2025-04-10T18:18:30.0838980Z »  	at org.opensearch.index.shard.IndexShardOperationPermits.acquire(IndexShardOperationPermits.java:310) ~[opensearch-3.0.0-beta1-SNAPSHOT.jar:3.0.0-beta1-SNAPSHOT]
2025-04-10T18:18:30.0841585Z »  	at org.opensearch.index.shard.IndexShardOperationPermits.acquire(IndexShardOperationPermits.java:255) ~[opensearch-3.0.0-beta1-SNAPSHOT.jar:3.0.0-beta1-SNAPSHOT]
2025-04-10T18:18:30.0843925Z »  	at org.opensearch.index.shard.IndexShard.acquirePrimaryOperationPermit(IndexShard.java:4174) ~[opensearch-3.0.0-beta1-SNAPSHOT.jar:3.0.0-beta1-SNAPSHOT]
2025-04-10T18:18:30.0846913Z »  	at org.opensearch.action.support.replication.TransportReplicationAction.acquirePrimaryOperationPermit(TransportReplicationAction.java:1262) ~[opensearch-3.0.0-beta1-SNAPSHOT.jar:3.0.0-beta1-SNAPSHOT]
2025-04-10T18:18:30.0850013Z »  	at org.opensearch.action.support.replication.TransportReplicationAction$AsyncPrimaryAction.doRun(TransportReplicationAction.java:544) ~[opensearch-3.0.0-beta1-SNAPSHOT.jar:3.0.0-beta1-SNAPSHOT]
2025-04-10T18:18:30.0852885Z »  	at org.opensearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:52) ~[opensearch-3.0.0-beta1-SNAPSHOT.jar:3.0.0-beta1-SNAPSHOT]
2025-04-10T18:18:30.0855836Z »  	at org.opensearch.action.support.replication.TransportReplicationAction.handlePrimaryRequest(TransportReplicationAction.java:483) ~[opensearch-3.0.0-beta1-SNAPSHOT.jar:3.0.0-beta1-SNAPSHOT]
2025-04-10T18:18:30.0858888Z »  	at org.opensearch.wlm.WorkloadManagementTransportInterceptor$RequestHandler.messageReceived(WorkloadManagementTransportInterceptor.java:63) ~[opensearch-3.0.0-beta1-SNAPSHOT.jar:3.0.0-beta1-SNAPSHOT]
2025-04-10T18:18:30.0861829Z »  	at org.opensearch.transport.RequestHandlerRegistry.processMessageReceived(RequestHandlerRegistry.java:108) ~[opensearch-3.0.0-beta1-SNAPSHOT.jar:3.0.0-beta1-SNAPSHOT]
2025-04-10T18:18:30.0864064Z »  	at org.opensearch.transport.TransportService$7.doRun(TransportService.java:1048) ~[opensearch-3.0.0-beta1-SNAPSHOT.jar:3.0.0-beta1-SNAPSHOT]
2025-04-10T18:18:30.0866590Z »  	at org.opensearch.common.util.concurrent.ThreadContext$ContextPreservingAbstractRunnable.doRun(ThreadContext.java:975) ~[opensearch-3.0.0-beta1-SNAPSHOT.jar:3.0.0-beta1-SNAPSHOT]
2025-04-10T18:18:30.0868936Z »  	at org.opensearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:52) ~[opensearch-3.0.0-beta1-SNAPSHOT.jar:3.0.0-beta1-SNAPSHOT]
2025-04-10T18:18:30.0870628Z »  	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) ~[?:?]
2025-04-10T18:18:30.0871981Z »  	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) ~[?:?]
2025-04-10T18:18:30.0872999Z »  	at java.base/java.lang.Thread.run(Thread.java:1583) [?:?]
2025-04-10T18:18:30.0875008Z »  Caused by: java.lang.SecurityException: Denied OPEN (read) access to file: /proc/cpuinfo, domain: ProtectionDomain  (file:/__w/k-NN/k-NN/build/testclusters/integTest-0/distro/3.0.0-ARCHIVE/lib/lucene-core-10.1.0.jar <no signer certificates>)

Note: JDK classes are filtered when extracting ProtectionDomains

With the failing call stack from above there are 4 unique ProtectionDomains:

  1. k-NN
  2. lucene-core
  3. opensearch
  4. opensearch-core

A ProtectionDomain is essentially analogous to a jar..its a little more than that, but OpenSearch has only exclusively tied it to a single "codeBase" (re: jar). (A ProtectionDomain could be mapped to multiple codebases if using the jarsigner, but my understanding is this feature of JSM was not used widely)

Since we are moving this here we are now only evaluating the permissions for k-NN instead of all of k-NN, lucene-core, opensearch and opensearch-core.

Limiting the stack walking would have the same effect, but as you pointed out its relying on classes marked for removal.

I'm leaving a comment here to make sure my understanding is correct and for others reading this, but there is nothing to be addressed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm leaving a comment here to make sure my understanding is correct and for others reading this, but there is nothing to be addressed.

Correct, threads have own stacks which we traverse.

PlatformUtils.isAVX2SupportedBySystem();
PlatformUtils.isAVX512SupportedBySystem();
PlatformUtils.isAVX512SPRSupportedBySystem();
});
}

@Override
public Map<String, Mapper.TypeParser> getMappers() {
return Collections.singletonMap(
Expand Down
14 changes: 14 additions & 0 deletions src/test/java/org/opensearch/knn/KNNSingleNodeTestCase.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@
import org.opensearch.test.OpenSearchSingleNodeTestCase;
import org.opensearch.test.hamcrest.OpenSearchAssertions;

import com.carrotsearch.randomizedtesting.ThreadFilter;
import com.carrotsearch.randomizedtesting.annotations.ThreadLeakFilters;

import java.io.IOException;
import java.util.Base64;
import java.util.Collection;
Expand All @@ -63,7 +66,18 @@
import static org.opensearch.knn.common.KNNConstants.MODEL_TIMESTAMP;
import static org.opensearch.knn.common.KNNConstants.VECTOR_DATA_TYPE_FIELD;

@ThreadLeakFilters(defaultFilters = true, filters = { KNNSingleNodeTestCase.ForkJoinFilter.class })
public class KNNSingleNodeTestCase extends OpenSearchSingleNodeTestCase {
/**
* The the ForkJoinPool.commonPool() never terminates until program shutdown.
*/
public static final class ForkJoinFilter implements ThreadFilter {
@Override
public boolean reject(Thread t) {
return t.getName().startsWith("ForkJoinPool.commonPool-worker");
}
}

@Override
public void setUp() throws Exception {
super.setUp();
Expand Down
33 changes: 29 additions & 4 deletions src/test/java/org/opensearch/knn/jni/PlatformUtilTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@
package org.opensearch.knn.jni;

import com.sun.jna.Platform;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.MockedStatic;
import org.opensearch.knn.KNNTestCase;
import oshi.util.platform.mac.SysctlUtil;

import java.nio.file.Files;
Expand All @@ -25,17 +28,24 @@
import static org.opensearch.knn.jni.PlatformUtils.isAVX512SupportedBySystem;
import static org.opensearch.knn.jni.PlatformUtils.isAVX512SPRSupportedBySystem;

public class PlatformUtilTests extends KNNTestCase {
public class PlatformUtilTests extends Assert {
public static final String MAC_CPU_FEATURES = "machdep.cpu.leaf7_features";
public static final String LINUX_PROC_CPU_INFO = "/proc/cpuinfo";

@Before
public void setUp() {
PlatformUtils.reset();
}

@Test
public void testIsAVX2SupportedBySystem_platformIsNotIntel_returnsFalse() {
try (MockedStatic<Platform> mockedPlatform = mockStatic(Platform.class)) {
mockedPlatform.when(Platform::isIntel).thenReturn(false);
assertFalse(isAVX2SupportedBySystem());
}
}

@Test
public void testIsAVX2SupportedBySystem_platformIsIntelWithOSAsWindows_returnsFalse() {
try (MockedStatic<Platform> mockedPlatform = mockStatic(Platform.class)) {
mockedPlatform.when(Platform::isIntel).thenReturn(true);
Expand All @@ -44,6 +54,7 @@ public void testIsAVX2SupportedBySystem_platformIsIntelWithOSAsWindows_returnsFa
}
}

@Test
public void testIsAVX2SupportedBySystem_platformIsMac_returnsTrue() {
try (MockedStatic<Platform> mockedPlatform = mockStatic(Platform.class)) {
mockedPlatform.when(Platform::isIntel).thenReturn(true);
Expand All @@ -59,6 +70,7 @@ public void testIsAVX2SupportedBySystem_platformIsMac_returnsTrue() {
}
}

@Test
public void testIsAVX2SupportedBySystem_platformIsMac_returnsFalse() {
try (MockedStatic<Platform> mockedPlatform = mockStatic(Platform.class)) {
mockedPlatform.when(Platform::isIntel).thenReturn(true);
Expand All @@ -72,6 +84,7 @@ public void testIsAVX2SupportedBySystem_platformIsMac_returnsFalse() {

}

@Test
public void testIsAVX2SupportedBySystem_platformIsMac_throwsExceptionReturnsFalse() {
try (MockedStatic<Platform> mockedPlatform = mockStatic(Platform.class)) {
mockedPlatform.when(Platform::isIntel).thenReturn(true);
Expand All @@ -98,6 +111,7 @@ public void testIsAVX2SupportedBySystem_platformIsLinux_returnsTrue() {
}
}

@Test
public void testIsAVX2SupportedBySystem_platformIsLinux_returnsFalse() {
try (MockedStatic<Platform> mockedPlatform = mockStatic(Platform.class)) {
mockedPlatform.when(Platform::isIntel).thenReturn(true);
Expand All @@ -112,6 +126,7 @@ public void testIsAVX2SupportedBySystem_platformIsLinux_returnsFalse() {

}

@Test
public void testIsAVX2SupportedBySystem_platformIsLinux_throwsExceptionReturnsFalse() {
try (MockedStatic<Platform> mockedPlatform = mockStatic(Platform.class)) {
mockedPlatform.when(Platform::isIntel).thenReturn(true);
Expand All @@ -127,21 +142,23 @@ public void testIsAVX2SupportedBySystem_platformIsLinux_throwsExceptionReturnsFa
}

// AVX512 tests

@Test
public void testIsAVX512SupportedBySystem_platformIsNotIntel_returnsFalse() {
try (MockedStatic<Platform> mockedPlatform = mockStatic(Platform.class)) {
mockedPlatform.when(Platform::isIntel).thenReturn(false);
assertFalse(isAVX512SupportedBySystem());
}
}

@Test
public void testIsAVX512SupportedBySystem_platformIsMac_returnsFalse() {
try (MockedStatic<Platform> mockedPlatform = mockStatic(Platform.class)) {
mockedPlatform.when(Platform::isMac).thenReturn(false);
assertFalse(isAVX512SupportedBySystem());
}
}

@Test
public void testIsAVX512SupportedBySystem_platformIsIntelMac_returnsFalse() {
try (MockedStatic<Platform> mockedPlatform = mockStatic(Platform.class)) {
mockedPlatform.when(Platform::isIntel).thenReturn(true);
Expand All @@ -150,6 +167,7 @@ public void testIsAVX512SupportedBySystem_platformIsIntelMac_returnsFalse() {
}
}

@Test
public void testIsAVX512SupportedBySystem_platformIsIntelWithOSAsWindows_returnsFalse() {
try (MockedStatic<Platform> mockedPlatform = mockStatic(Platform.class)) {
mockedPlatform.when(Platform::isIntel).thenReturn(true);
Expand All @@ -158,6 +176,7 @@ public void testIsAVX512SupportedBySystem_platformIsIntelWithOSAsWindows_returns
}
}

@Test
public void testIsAVX512SupportedBySystem_platformIsLinuxAllAVX512FlagsPresent_returnsTrue() {
try (MockedStatic<Platform> mockedPlatform = mockStatic(Platform.class)) {
mockedPlatform.when(Platform::isIntel).thenReturn(true);
Expand All @@ -171,6 +190,7 @@ public void testIsAVX512SupportedBySystem_platformIsLinuxAllAVX512FlagsPresent_r
}
}

@Test
public void testIsAVX512SupportedBySystem_platformIsLinuxSomeAVX512FlagsPresent_returnsFalse() {
try (MockedStatic<Platform> mockedPlatform = mockStatic(Platform.class)) {
mockedPlatform.when(Platform::isIntel).thenReturn(true);
Expand All @@ -185,21 +205,23 @@ public void testIsAVX512SupportedBySystem_platformIsLinuxSomeAVX512FlagsPresent_
}

// Tests AVX512 instructions available since Intel(R) Sapphire Rapids.

@Test
public void testIsAVX512SPRSupportedBySystem_platformIsNotIntel_returnsFalse() {
try (MockedStatic<Platform> mockedPlatform = mockStatic(Platform.class)) {
mockedPlatform.when(Platform::isIntel).thenReturn(false);
assertFalse(isAVX512SPRSupportedBySystem());
}
}

@Test
public void testIsAVX512SPRSupportedBySystem_platformIsMac_returnsFalse() {
try (MockedStatic<Platform> mockedPlatform = mockStatic(Platform.class)) {
mockedPlatform.when(Platform::isMac).thenReturn(false);
assertFalse(isAVX512SPRSupportedBySystem());
}
}

@Test
public void testIsAVX512SPRSupportedBySystem_platformIsIntelMac_returnsFalse() {
try (MockedStatic<Platform> mockedPlatform = mockStatic(Platform.class)) {
mockedPlatform.when(Platform::isIntel).thenReturn(true);
Expand All @@ -208,6 +230,7 @@ public void testIsAVX512SPRSupportedBySystem_platformIsIntelMac_returnsFalse() {
}
}

@Test
public void testIsAVX512SPRSupportedBySystem_platformIsIntelWithOSAsWindows_returnsFalse() {
try (MockedStatic<Platform> mockedPlatform = mockStatic(Platform.class)) {
mockedPlatform.when(Platform::isIntel).thenReturn(true);
Expand All @@ -216,6 +239,7 @@ public void testIsAVX512SPRSupportedBySystem_platformIsIntelWithOSAsWindows_retu
}
}

@Test
public void testIsAVX512SPRSupportedBySystem_platformIsLinuxAllAVX512SPRFlagsPresent_returnsTrue() {
try (MockedStatic<Platform> mockedPlatform = mockStatic(Platform.class)) {
mockedPlatform.when(Platform::isIntel).thenReturn(true);
Expand All @@ -229,6 +253,7 @@ public void testIsAVX512SPRSupportedBySystem_platformIsLinuxAllAVX512SPRFlagsPre
}
}

@Test
public void testIsAVX512SPRSupportedBySystem_platformIsLinuxSomeAVX512SPRFlagsPresent_returnsFalse() {
try (MockedStatic<Platform> mockedPlatform = mockStatic(Platform.class)) {
mockedPlatform.when(Platform::isIntel).thenReturn(true);
Expand Down
Loading