This is an automated email from the ASF dual-hosted git repository. yasith pushed a commit to branch AIRAVATA-3981/integration-health-check in repository https://gitbox.apache.org/repos/asf/airavata.git
commit 12deed3ee683834400f99c8ab693274fe38a0ee4 Author: yasithdev <[email protected]> AuthorDate: Thu Mar 26 15:33:56 2026 -0500 feat: add Database, RabbitMQ, and Kafka integration health tests --- .../airavata/integration/DatabaseHealthTest.java | 85 ++++++++++++++++++++++ .../airavata/integration/KafkaHealthTest.java | 58 +++++++++++++++ .../airavata/integration/RabbitMQHealthTest.java | 74 +++++++++++++++++++ 3 files changed, 217 insertions(+) diff --git a/integration-tests/src/test/java/org/apache/airavata/integration/DatabaseHealthTest.java b/integration-tests/src/test/java/org/apache/airavata/integration/DatabaseHealthTest.java new file mode 100644 index 0000000000..ce9fd48f8c --- /dev/null +++ b/integration-tests/src/test/java/org/apache/airavata/integration/DatabaseHealthTest.java @@ -0,0 +1,85 @@ +/** + * + * 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. + */ +package org.apache.airavata.integration; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Stream; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +/** + * Verifies JDBC connectivity to the Airavata database and the presence of + * core tables required for experiment and resource management. + */ +@Tag("integration") +class DatabaseHealthTest { + + private static final String HOST = + System.getProperty("airavata.db.host", "localhost"); + private static final int PORT = + Integer.parseInt(System.getProperty("airavata.db.port", "13306")); + private static final String DATABASE = + System.getProperty("airavata.db.name", "airavata"); + private static final String USER = + System.getProperty("airavata.db.user", "airavata"); + private static final String PASSWORD = + System.getProperty("airavata.db.password", "123456"); + + private static final String JDBC_URL = + "jdbc:mariadb://" + HOST + ":" + PORT + "/" + DATABASE; + + static Stream<String> requiredTables() { + return Stream.of( + "EXPERIMENT", + "APPLICATION_DEPLOYMENT", + "COMPUTE_RESOURCE", + "GATEWAY", + "USER_PROFILE", + "SHARING_ENTITY", + "CREDENTIAL"); + } + + @ParameterizedTest(name = "table {0} exists") + @MethodSource("requiredTables") + void requiredTableShouldExist(String tableName) throws Exception { + try (Connection connection = DriverManager.getConnection(JDBC_URL, USER, PASSWORD)) { + assertTrue(connection.isValid(5), "Database connection is not valid"); + + DatabaseMetaData meta = connection.getMetaData(); + List<String> found = new ArrayList<>(); + try (ResultSet rs = meta.getTables(DATABASE, null, tableName, new String[]{"TABLE"})) { + while (rs.next()) { + found.add(rs.getString("TABLE_NAME")); + } + } + assertTrue( + found.stream().anyMatch(t -> t.equalsIgnoreCase(tableName)), + "Expected table '" + tableName + "' was not found in database '" + DATABASE + "'"); + } + } +} diff --git a/integration-tests/src/test/java/org/apache/airavata/integration/KafkaHealthTest.java b/integration-tests/src/test/java/org/apache/airavata/integration/KafkaHealthTest.java new file mode 100644 index 0000000000..45b0f800de --- /dev/null +++ b/integration-tests/src/test/java/org/apache/airavata/integration/KafkaHealthTest.java @@ -0,0 +1,58 @@ +/** + * + * 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. + */ +package org.apache.airavata.integration; + +import static org.junit.jupiter.api.Assertions.assertFalse; + +import java.util.Collection; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.ExecutionException; +import org.apache.kafka.clients.admin.AdminClient; +import org.apache.kafka.clients.admin.AdminClientConfig; +import org.apache.kafka.clients.admin.DescribeClusterResult; +import org.apache.kafka.common.Node; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; + +/** + * Verifies that the Kafka cluster is reachable and has at least one broker node. + */ +@Tag("integration") +class KafkaHealthTest { + + private static final String BOOTSTRAP_SERVERS = + System.getProperty("airavata.kafka.bootstrap.servers", "localhost:9092"); + + @Test + void kafkaClusterShouldHaveAtLeastOneBroker() throws ExecutionException, InterruptedException { + Properties config = new Properties(); + config.put(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG, BOOTSTRAP_SERVERS); + config.put(AdminClientConfig.REQUEST_TIMEOUT_MS_CONFIG, "10000"); + config.put(AdminClientConfig.DEFAULT_API_TIMEOUT_MS_CONFIG, "10000"); + + try (AdminClient adminClient = AdminClient.create(config)) { + DescribeClusterResult result = adminClient.describeCluster(); + Collection<Node> nodes = result.nodes().get(); + + assertFalse(nodes.isEmpty(), "Kafka cluster reported no broker nodes"); + } + } +} diff --git a/integration-tests/src/test/java/org/apache/airavata/integration/RabbitMQHealthTest.java b/integration-tests/src/test/java/org/apache/airavata/integration/RabbitMQHealthTest.java new file mode 100644 index 0000000000..597e61d159 --- /dev/null +++ b/integration-tests/src/test/java/org/apache/airavata/integration/RabbitMQHealthTest.java @@ -0,0 +1,74 @@ +/** + * + * 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. + */ +package org.apache.airavata.integration; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +import com.rabbitmq.client.Channel; +import com.rabbitmq.client.Connection; +import com.rabbitmq.client.ConnectionFactory; +import java.util.stream.Stream; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +/** + * Verifies AMQP connectivity to RabbitMQ and that the core Airavata exchanges + * are already declared (passive declare — does not create them). + */ +@Tag("integration") +class RabbitMQHealthTest { + + private static final String HOST = + System.getProperty("airavata.rabbitmq.host", "localhost"); + private static final int PORT = + Integer.parseInt(System.getProperty("airavata.rabbitmq.port", "5672")); + private static final String USERNAME = + System.getProperty("airavata.rabbitmq.username", "airavata"); + private static final String PASSWORD = + System.getProperty("airavata.rabbitmq.password", "airavata"); + private static final String VHOST = + System.getProperty("airavata.rabbitmq.vhost", "/"); + + static Stream<String> exchanges() { + return Stream.of( + "experiment_exchange", + "process_exchange", + "status_exchange"); + } + + @ParameterizedTest(name = "exchange {0} is declared") + @MethodSource("exchanges") + void exchangeShouldBeDeclared(String exchangeName) throws Exception { + ConnectionFactory factory = new ConnectionFactory(); + factory.setHost(HOST); + factory.setPort(PORT); + factory.setUsername(USERNAME); + factory.setPassword(PASSWORD); + factory.setVirtualHost(VHOST); + + try (Connection connection = factory.newConnection(); + Channel channel = connection.createChannel()) { + assertDoesNotThrow( + () -> channel.exchangeDeclarePassive(exchangeName), + "Exchange '" + exchangeName + "' is not declared in RabbitMQ"); + } + } +}
