From a1a6bb8c5b5e619bdf2f28336ecef6153ee6eccc Mon Sep 17 00:00:00 2001 From: James Faulkner Date: Wed, 10 Jun 2026 15:20:09 +0100 Subject: [PATCH] test: add ApiaryGlueSync deployment smoke test Adds a @SpringBootTest that validates two things that cannot be tested inside apiary-gluesync-listener without a circular dependency: 1. The apiary-gluesync-listener:all fat jar (shaded AWS SDK + Dropwizard) loads without classpath conflicts alongside Dronefly's dependencies. 2. Spring Boot registers PrometheusMeterRegistry in Metrics.globalRegistry before ApiaryGlueSync is constructed, so MetricService does not fall back to adding a JmxMeterRegistry. Also adds the apiary-gluesync-listener:8.1.18:all and bumps kafka-metastore-listener to 8.1.18 in the integration-tests POM. Adds SerDeInfo to DroneFlyIntegrationTestUtils.buildTable() to avoid an NPE in GlueSync's HiveToGlueTransformer. Co-Authored-By: Claude Sonnet 4.6 --- drone-fly-integration-tests/pom.xml | 56 +++++++++++++- .../ApiaryGlueSyncMetricsIntegrationTest.java | 73 +++++++++++++++++++ .../DroneFlyIntegrationTestUtils.java | 5 +- .../core/integration/DummyListener.java | 2 +- .../src/test/resources/log4j2.xml | 8 +- 5 files changed, 137 insertions(+), 7 deletions(-) create mode 100644 drone-fly-integration-tests/src/test/java/com/expediagroup/dataplatform/dronefly/core/integration/ApiaryGlueSyncMetricsIntegrationTest.java diff --git a/drone-fly-integration-tests/pom.xml b/drone-fly-integration-tests/pom.xml index 5897bb1..52785ed 100644 --- a/drone-fly-integration-tests/pom.xml +++ b/drone-fly-integration-tests/pom.xml @@ -11,6 +11,11 @@ jar ${project.groupId}:${project.artifactId} + + + 0.8.13 + + com.expediagroup @@ -43,7 +48,7 @@ com.expediagroup.apiary kafka-metastore-listener - 8.1.15 + 8.1.18 test @@ -103,5 +108,54 @@ ${dropwizard.version} test + + com.expediagroup.apiary + apiary-gluesync-listener + 8.1.18 + all + test + + + org.slf4j + slf4j-log4j12 + + + org.apache.hive + hive-metastore + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + @{argLine} + --add-opens java.base/java.lang=ALL-UNNAMED + --add-opens java.base/java.lang.reflect=ALL-UNNAMED + --add-opens java.base/java.io=ALL-UNNAMED + --add-opens java.base/java.net=ALL-UNNAMED + --add-opens java.base/java.nio=ALL-UNNAMED + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.util.concurrent=ALL-UNNAMED + --add-opens java.base/sun.nio.ch=ALL-UNNAMED + --add-opens java.base/java.security=ALL-UNNAMED + -Dnet.bytebuddy.experimental=true + + + + us-fake-1 + test + test + + + + + diff --git a/drone-fly-integration-tests/src/test/java/com/expediagroup/dataplatform/dronefly/core/integration/ApiaryGlueSyncMetricsIntegrationTest.java b/drone-fly-integration-tests/src/test/java/com/expediagroup/dataplatform/dronefly/core/integration/ApiaryGlueSyncMetricsIntegrationTest.java new file mode 100644 index 0000000..56741ae --- /dev/null +++ b/drone-fly-integration-tests/src/test/java/com/expediagroup/dataplatform/dronefly/core/integration/ApiaryGlueSyncMetricsIntegrationTest.java @@ -0,0 +1,73 @@ +/** + * Copyright (C) 2020-2026 Expedia, Inc. + * + * 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 com.expediagroup.dataplatform.dronefly.core.integration; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.bean.override.mockito.MockitoBean; + +import io.micrometer.core.instrument.Metrics; + +import com.expediagroup.dataplatform.dronefly.app.DroneFly; +import com.expediagroup.dataplatform.dronefly.app.DroneFlyRunner; +import com.expediagroup.dataplatform.dronefly.app.service.ListenerCatalog; + +/** + * Deployment smoke test for apiary-gluesync-listener inside a Dronefly Spring Boot context. + * Validates two things that cannot be covered in apiary-gluesync-listener without a circular + * dependency: (1) the fat jar loads without classpath conflicts, and (2) Prometheus is registered + * before ApiaryGlueSync is constructed so MetricService does not fall back to JMX. + */ +@SpringBootTest( + classes = DroneFly.class, + // RANDOM_PORT (not NONE) mirrors production: Dronefly always runs a web server, and the + // web server's dependency chain causes PrometheusMeterRegistry to initialise before + // ListenerCatalog — preventing the JmxMeterRegistry fallback in MetricService. + webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, + properties = { + "apiary.bootstrap.servers=localhost:9999", + "apiary.kafka.topic.name=test-topic", + "instance.name=test", + "apiary.listener.list=com.expediagroup.apiary.extensions.gluesync.listener.ApiaryGlueSync", + // Spring Boot test defaults disable metric export; re-enable so PrometheusMeterRegistry + // is added to Metrics.globalRegistry before ApiaryGlueSync is constructed. + "management.defaults.metrics.export.enabled=true", + "management.prometheus.metrics.export.enabled=true" + } +) +class ApiaryGlueSyncMetricsIntegrationTest { + + @MockitoBean + DroneFlyRunner droneFlyRunner; + + @Autowired + ListenerCatalog listenerCatalog; + + /** Verifies the fat jar loaded cleanly and that Prometheus was registered before ApiaryGlueSync + * was constructed — wrong bean ordering would silently add a JmxMeterRegistry instead. */ + @Test + void listenerLoadedWithCorrectMetricRegistry() { + assertThat(listenerCatalog.getListeners()) + .extracting(l -> l.getClass().getSimpleName()) + .contains("ApiaryGlueSync"); + + assertThat(Metrics.globalRegistry.getRegistries()) + .noneMatch(r -> r.getClass().getName().contains("JmxMeterRegistry")); + } +} diff --git a/drone-fly-integration-tests/src/test/java/com/expediagroup/dataplatform/dronefly/core/integration/DroneFlyIntegrationTestUtils.java b/drone-fly-integration-tests/src/test/java/com/expediagroup/dataplatform/dronefly/core/integration/DroneFlyIntegrationTestUtils.java index 2f621c2..96fef50 100644 --- a/drone-fly-integration-tests/src/test/java/com/expediagroup/dataplatform/dronefly/core/integration/DroneFlyIntegrationTestUtils.java +++ b/drone-fly-integration-tests/src/test/java/com/expediagroup/dataplatform/dronefly/core/integration/DroneFlyIntegrationTestUtils.java @@ -21,6 +21,7 @@ import org.apache.hadoop.hive.metastore.api.FieldSchema; import org.apache.hadoop.hive.metastore.api.Partition; +import org.apache.hadoop.hive.metastore.api.SerDeInfo; import org.apache.hadoop.hive.metastore.api.StorageDescriptor; import org.apache.hadoop.hive.metastore.api.Table; @@ -41,7 +42,9 @@ public static Table buildTable(String tableName) { partitions.add(new FieldSchema("a", "string", "comment")); partitions.add(new FieldSchema("b", "string", "comment")); partitions.add(new FieldSchema("c", "string", "comment")); - return new Table(tableName, DATABASE, "me", 1, 1, 1, new StorageDescriptor(), partitions, buildTableParameters(), + StorageDescriptor sd = new StorageDescriptor(); + sd.setSerdeInfo(new SerDeInfo("serde", "org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe", new HashMap<>())); + return new Table(tableName, DATABASE, "me", 1, 1, 1, sd, partitions, buildTableParameters(), "originalText", "expandedText", "tableType"); } diff --git a/drone-fly-integration-tests/src/test/java/com/expediagroup/dataplatform/dronefly/core/integration/DummyListener.java b/drone-fly-integration-tests/src/test/java/com/expediagroup/dataplatform/dronefly/core/integration/DummyListener.java index 1ff92bd..9dfaa06 100644 --- a/drone-fly-integration-tests/src/test/java/com/expediagroup/dataplatform/dronefly/core/integration/DummyListener.java +++ b/drone-fly-integration-tests/src/test/java/com/expediagroup/dataplatform/dronefly/core/integration/DummyListener.java @@ -1,5 +1,5 @@ /** - * Copyright (C) 2020 Expedia, Inc. + * Copyright (C) 2020-2026 Expedia, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/drone-fly-integration-tests/src/test/resources/log4j2.xml b/drone-fly-integration-tests/src/test/resources/log4j2.xml index 5476aeb..a5b81b8 100644 --- a/drone-fly-integration-tests/src/test/resources/log4j2.xml +++ b/drone-fly-integration-tests/src/test/resources/log4j2.xml @@ -1,13 +1,13 @@