diff --git a/impl/test/src/test/java/io/serverlessworkflow/impl/test/CustomFunctionTest.java b/impl/test/src/test/java/io/serverlessworkflow/impl/test/CustomFunctionTest.java index b659b7af0..f21107a10 100644 --- a/impl/test/src/test/java/io/serverlessworkflow/impl/test/CustomFunctionTest.java +++ b/impl/test/src/test/java/io/serverlessworkflow/impl/test/CustomFunctionTest.java @@ -21,6 +21,7 @@ import io.serverlessworkflow.impl.WorkflowApplication; import io.serverlessworkflow.impl.WorkflowException; +import io.serverlessworkflow.impl.test.junit.DisabledIfPythonUnavailable; import java.io.IOException; import java.util.Map; import org.junit.jupiter.api.AfterAll; @@ -58,6 +59,7 @@ void testCustomFunction() { .isEqualTo(404); } + @DisabledIfPythonUnavailable() @ParameterizedTest @ValueSource( strings = { diff --git a/impl/test/src/test/java/io/serverlessworkflow/impl/test/grpc/GrpcBiDirectionalStreamingTest.java b/impl/test/src/test/java/io/serverlessworkflow/impl/test/grpc/GrpcBiDirectionalStreamingTest.java index aa34497aa..bbde7cf0d 100644 --- a/impl/test/src/test/java/io/serverlessworkflow/impl/test/grpc/GrpcBiDirectionalStreamingTest.java +++ b/impl/test/src/test/java/io/serverlessworkflow/impl/test/grpc/GrpcBiDirectionalStreamingTest.java @@ -23,6 +23,7 @@ import io.serverlessworkflow.impl.WorkflowDefinition; import io.serverlessworkflow.impl.WorkflowModel; import io.serverlessworkflow.impl.test.grpc.handlers.ContributorBiDiStreamingHandler; +import io.serverlessworkflow.impl.test.junit.DisabledIfProtocUnavailable; import java.io.IOException; import java.util.Collection; import java.util.Map; @@ -31,6 +32,7 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +@DisabledIfProtocUnavailable public class GrpcBiDirectionalStreamingTest { private static final int PORT_FOR_EXAMPLES = 5011; diff --git a/impl/test/src/test/java/io/serverlessworkflow/impl/test/grpc/GrpcClientStreamingTest.java b/impl/test/src/test/java/io/serverlessworkflow/impl/test/grpc/GrpcClientStreamingTest.java index aca9615db..f22c34d5a 100644 --- a/impl/test/src/test/java/io/serverlessworkflow/impl/test/grpc/GrpcClientStreamingTest.java +++ b/impl/test/src/test/java/io/serverlessworkflow/impl/test/grpc/GrpcClientStreamingTest.java @@ -22,6 +22,7 @@ import io.serverlessworkflow.impl.WorkflowApplication; import io.serverlessworkflow.impl.WorkflowDefinition; import io.serverlessworkflow.impl.test.grpc.handlers.ContributorClientStreamingHandler; +import io.serverlessworkflow.impl.test.junit.DisabledIfProtocUnavailable; import java.io.IOException; import java.util.List; import java.util.Map; @@ -30,6 +31,7 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +@DisabledIfProtocUnavailable public class GrpcClientStreamingTest { private static final int PORT_FOR_EXAMPLES = 5011; diff --git a/impl/test/src/test/java/io/serverlessworkflow/impl/test/grpc/GrpcServerStreamingTest.java b/impl/test/src/test/java/io/serverlessworkflow/impl/test/grpc/GrpcServerStreamingTest.java index 78ac67ca2..5f18ca670 100644 --- a/impl/test/src/test/java/io/serverlessworkflow/impl/test/grpc/GrpcServerStreamingTest.java +++ b/impl/test/src/test/java/io/serverlessworkflow/impl/test/grpc/GrpcServerStreamingTest.java @@ -23,6 +23,7 @@ import io.serverlessworkflow.impl.WorkflowDefinition; import io.serverlessworkflow.impl.WorkflowModel; import io.serverlessworkflow.impl.test.grpc.handlers.ContributorServerStreamingHandler; +import io.serverlessworkflow.impl.test.junit.DisabledIfProtocUnavailable; import java.io.IOException; import java.util.Collection; import java.util.Map; @@ -31,6 +32,7 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +@DisabledIfProtocUnavailable public class GrpcServerStreamingTest { private static final int PORT_FOR_EXAMPLES = 5011; diff --git a/impl/test/src/test/java/io/serverlessworkflow/impl/test/grpc/GrpcUnaryArgsExprTest.java b/impl/test/src/test/java/io/serverlessworkflow/impl/test/grpc/GrpcUnaryArgsExprTest.java index 59777fb01..594b481e5 100644 --- a/impl/test/src/test/java/io/serverlessworkflow/impl/test/grpc/GrpcUnaryArgsExprTest.java +++ b/impl/test/src/test/java/io/serverlessworkflow/impl/test/grpc/GrpcUnaryArgsExprTest.java @@ -22,6 +22,7 @@ import io.serverlessworkflow.impl.WorkflowApplication; import io.serverlessworkflow.impl.WorkflowDefinition; import io.serverlessworkflow.impl.test.grpc.handlers.ContributorUnaryArgsExprHandler; +import io.serverlessworkflow.impl.test.junit.DisabledIfProtocUnavailable; import java.io.IOException; import java.util.Map; import org.assertj.core.api.Assertions; @@ -29,6 +30,7 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +@DisabledIfProtocUnavailable public class GrpcUnaryArgsExprTest { private static final int PORT_FOR_EXAMPLES = 5011; diff --git a/impl/test/src/test/java/io/serverlessworkflow/impl/test/grpc/GrpcUnaryTest.java b/impl/test/src/test/java/io/serverlessworkflow/impl/test/grpc/GrpcUnaryTest.java index 6205ff27e..bce72a72e 100644 --- a/impl/test/src/test/java/io/serverlessworkflow/impl/test/grpc/GrpcUnaryTest.java +++ b/impl/test/src/test/java/io/serverlessworkflow/impl/test/grpc/GrpcUnaryTest.java @@ -22,6 +22,7 @@ import io.serverlessworkflow.impl.WorkflowApplication; import io.serverlessworkflow.impl.WorkflowDefinition; import io.serverlessworkflow.impl.test.grpc.handlers.PersonUnaryHandler; +import io.serverlessworkflow.impl.test.junit.DisabledIfProtocUnavailable; import java.io.IOException; import java.util.Map; import org.assertj.core.api.Assertions; @@ -29,6 +30,7 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +@DisabledIfProtocUnavailable public class GrpcUnaryTest { private static final int PORT_FOR_EXAMPLES = 5011; diff --git a/impl/test/src/test/java/io/serverlessworkflow/impl/test/junit/BinaryCheckUtil.java b/impl/test/src/test/java/io/serverlessworkflow/impl/test/junit/BinaryCheckUtil.java new file mode 100644 index 000000000..c2f9f1da0 --- /dev/null +++ b/impl/test/src/test/java/io/serverlessworkflow/impl/test/junit/BinaryCheckUtil.java @@ -0,0 +1,53 @@ +/* + * Copyright 2020-Present The Serverless Workflow Specification Authors + * + * Licensed 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. + */ +package io.serverlessworkflow.impl.test.junit; + +import java.io.IOException; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.TimeUnit; + +public final class BinaryCheckUtil { + + private BinaryCheckUtil() {} + + private static final ConcurrentMap BINARY_CHECKS = new ConcurrentHashMap<>(); + + public static boolean isBinaryAvailable(String... command) { + return BINARY_CHECKS.computeIfAbsent( + String.join(" ", command), + __ -> { + try { + Process process = + new ProcessBuilder(command) + .redirectErrorStream(true) + .redirectOutput(ProcessBuilder.Redirect.DISCARD) + .start(); + boolean finished = process.waitFor(2, TimeUnit.SECONDS); + if (finished) { + return process.exitValue() == 0; + } + process.destroyForcibly(); + return false; + } catch (IOException | InterruptedException e) { + if (e instanceof InterruptedException) { + Thread.currentThread().interrupt(); + } + return false; + } + }); + } +} diff --git a/impl/test/src/test/java/io/serverlessworkflow/impl/test/junit/DisabledIfProtocUnavailable.java b/impl/test/src/test/java/io/serverlessworkflow/impl/test/junit/DisabledIfProtocUnavailable.java new file mode 100644 index 000000000..5b91e3a9d --- /dev/null +++ b/impl/test/src/test/java/io/serverlessworkflow/impl/test/junit/DisabledIfProtocUnavailable.java @@ -0,0 +1,27 @@ +/* + * Copyright 2020-Present The Serverless Workflow Specification Authors + * + * Licensed 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. + */ +package io.serverlessworkflow.impl.test.junit; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.junit.jupiter.api.extension.ExtendWith; + +@Target({ElementType.TYPE, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@ExtendWith(ProtocCheckCondition.class) +public @interface DisabledIfProtocUnavailable {} diff --git a/impl/test/src/test/java/io/serverlessworkflow/impl/test/junit/DisabledIfPythonUnavailable.java b/impl/test/src/test/java/io/serverlessworkflow/impl/test/junit/DisabledIfPythonUnavailable.java new file mode 100644 index 000000000..dcaa116e1 --- /dev/null +++ b/impl/test/src/test/java/io/serverlessworkflow/impl/test/junit/DisabledIfPythonUnavailable.java @@ -0,0 +1,27 @@ +/* + * Copyright 2020-Present The Serverless Workflow Specification Authors + * + * Licensed 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. + */ +package io.serverlessworkflow.impl.test.junit; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.junit.jupiter.api.extension.ExtendWith; + +@Target({ElementType.TYPE, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@ExtendWith(PythonCheckCondition.class) +public @interface DisabledIfPythonUnavailable {} diff --git a/impl/test/src/test/java/io/serverlessworkflow/impl/test/junit/ProtocCheckCondition.java b/impl/test/src/test/java/io/serverlessworkflow/impl/test/junit/ProtocCheckCondition.java new file mode 100644 index 000000000..1d7f3ad26 --- /dev/null +++ b/impl/test/src/test/java/io/serverlessworkflow/impl/test/junit/ProtocCheckCondition.java @@ -0,0 +1,66 @@ +/* + * Copyright 2020-Present The Serverless Workflow Specification Authors + * + * Licensed 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. + */ +package io.serverlessworkflow.impl.test.junit; + +import static io.serverlessworkflow.impl.test.junit.BinaryCheckUtil.isBinaryAvailable; + +import com.github.os72.protocjar.Protoc; +import java.util.concurrent.atomic.AtomicReference; +import org.junit.jupiter.api.extension.ConditionEvaluationResult; +import org.junit.jupiter.api.extension.ExecutionCondition; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.platform.commons.util.AnnotationUtils; + +public class ProtocCheckCondition implements ExecutionCondition { + + private static final AtomicReference protocAvailable = new AtomicReference<>(null); + + @Override + public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) { + return AnnotationUtils.findAnnotation(context.getElement(), DisabledIfProtocUnavailable.class) + .map( + annotation -> { + if (isProtocAvailable()) { + return ConditionEvaluationResult.enabled( + "Protoc is available for the current platform."); + } else { + return ConditionEvaluationResult.disabled( + "Test disabled: Protoc not currently available not found."); + } + }) + .orElse(ConditionEvaluationResult.enabled("No @DisabledIfProtocUnavailable found.")); + } + + private boolean isProtocAvailable() { + Boolean cached = protocAvailable.get(); + if (cached != null) { + return cached; + } + + boolean found = false; + try { + if (Protoc.runProtoc(new String[] {"--version"}) == 0) found = true; + } catch (Exception e) { + // ignore + } + + if (!found) found = isBinaryAvailable("protoc", "--version"); + + protocAvailable.compareAndSet(null, found); + + return protocAvailable.get(); + } +} diff --git a/impl/test/src/test/java/io/serverlessworkflow/impl/test/junit/PythonCheckCondition.java b/impl/test/src/test/java/io/serverlessworkflow/impl/test/junit/PythonCheckCondition.java new file mode 100644 index 000000000..8ea147600 --- /dev/null +++ b/impl/test/src/test/java/io/serverlessworkflow/impl/test/junit/PythonCheckCondition.java @@ -0,0 +1,44 @@ +/* + * Copyright 2020-Present The Serverless Workflow Specification Authors + * + * Licensed 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. + */ +package io.serverlessworkflow.impl.test.junit; + +import static io.serverlessworkflow.impl.test.junit.BinaryCheckUtil.isBinaryAvailable; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import org.junit.jupiter.api.extension.ConditionEvaluationResult; +import org.junit.jupiter.api.extension.ExecutionCondition; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.platform.commons.util.AnnotationUtils; + +public class PythonCheckCondition implements ExecutionCondition { + + private static final ConcurrentMap BINARY_CHECKS = new ConcurrentHashMap<>(); + + @Override + public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) { + return AnnotationUtils.findAnnotation(context.getElement(), DisabledIfPythonUnavailable.class) + .map( + annotation -> { + if (isBinaryAvailable("python", "--version")) { + return ConditionEvaluationResult.enabled("Python is available."); + } else { + return ConditionEvaluationResult.disabled("Test disabled: Python not found."); + } + }) + .orElse(ConditionEvaluationResult.enabled("No @DisabledIfBinaryUnavailable found.")); + } +}