This is an automated email from the ASF dual-hosted git repository.

danny0405 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hudi.git


The following commit(s) were added to refs/heads/master by this push:
     new 0b1c0e09c9f3 test(spark): make sync_validate fail-fast pins 
independent of libthrift resolution (#19681)
0b1c0e09c9f3 is described below

commit 0b1c0e09c9f3d9da9f2b8e1ede88ff4a8fc009a7
Author: voonhous <[email protected]>
AuthorDate: Fri Aug 21 11:31:03 2026 +0800

    test(spark): make sync_validate fail-fast pins independent of libthrift 
resolution (#19681)
    
    The last test in TestValidateHoodieSyncProcedure expected a portless 
jdbc:hive2 URL to fail in transport setup with an SQLException, but with 
spark-hive's libthrift 0.12.0 on the classpath the Hive 2.3.10 driver dies 
there with NoClassDefFoundError: TConfiguration (see #19680), which broke the 
latestPartitions pin. Use a hostless URL instead so the driver rejects it 
during URL parsing with JdbcUriParseException (an SQLException) before any 
thrift class loads.
    
    Closes #19679
---
 .../TestValidateHoodieSyncProcedure.scala          | 24 ++++++++++++++--------
 1 file changed, 16 insertions(+), 8 deletions(-)

diff --git 
a/hudi-spark-datasource/hudi-spark/src/test/scala/org/apache/spark/sql/hudi/procedure/TestValidateHoodieSyncProcedure.scala
 
b/hudi-spark-datasource/hudi-spark/src/test/scala/org/apache/spark/sql/hudi/procedure/TestValidateHoodieSyncProcedure.scala
index 2cc640e7e971..7b0fcfaf16ed 100644
--- 
a/hudi-spark-datasource/hudi-spark/src/test/scala/org/apache/spark/sql/hudi/procedure/TestValidateHoodieSyncProcedure.scala
+++ 
b/hudi-spark-datasource/hudi-spark/src/test/scala/org/apache/spark/sql/hudi/procedure/TestValidateHoodieSyncProcedure.scala
@@ -25,9 +25,14 @@ import java.sql.SQLException
  * Tests for 
[[org.apache.spark.sql.hudi.command.procedures.ValidateHoodieSyncProcedure]].
  *
  * The "complete" / "latestPartitions" modes count records over JDBC, but they 
do not need a live
- * Hive/JDBC endpoint to be exercised negatively: pointed at a portless URL, 
both fail fast in the
- * driver's transport setup, which rejects the invalid port before any network 
connect. The last
- * test pins those two failure shapes, one of which is the connection-failure 
masking bug of #19635.
+ * Hive/JDBC endpoint to be exercised negatively: pointed at a hostless URL, 
both fail fast in the
+ * driver's URL parsing, which raises JdbcUriParseException (an SQLException) 
before any transport
+ * class loads or any network connect. The last test pins those two failure 
shapes, one of which is
+ * the connection-failure masking bug of #19635. Failing during parsing, not 
transport setup, keeps
+ * the pins independent of libthrift resolution: the Hive 2.3.10 client jars 
need libthrift 0.14.1
+ * (TConfiguration), but spark-hive pulls 0.12.0 onto the test classpath, so a 
connect attempt that
+ * reaches HiveAuthUtils.getSocketTransport dies with NoClassDefFoundError 
instead of the
+ * SQLException these pins rely on, see #19680.
  *
  * The other tests pass 'noop', which short-circuits the record counting 
(record counts stay 0)
  * while still exercising the timeline comparison, the catch-up-commit 
computation and the result
@@ -207,7 +212,7 @@ class TestValidateHoodieSyncProcedure extends 
HoodieSparkProcedureTestBase {
     }
   }
 
-  test("Test Call sync_validate record-count modes fail fast on an unreachable 
HiveServer2") {
+  test("Test Call sync_validate record-count modes fail fast on an unusable 
HiveServer2 url") {
     withTempDir { tmp =>
       val tableName = generateTableName
       createTable(tableName, s"${tmp.getCanonicalPath}/$tableName")
@@ -215,8 +220,11 @@ class TestValidateHoodieSyncProcedure extends 
HoodieSparkProcedureTestBase {
 
       // The mode dispatch counts records before the timelines are compared, 
so a single table as
       // both source and target is enough here: neither call survives the 
record counting.
-      // Nothing reaches the network either: the url carries no port, so the 
authority resolves to
-      // unused:-1 and the driver's transport setup rejects that port before 
any connect.
+      // Nothing reaches the network either: the url has no host, so 
Utils.configureConnParams
+      // rejects it with JdbcUriParseException (an SQLException) while 
parsing, before the driver
+      // touches any thrift transport class. That last part is load-bearing, 
see #19680: with
+      // spark-hive's libthrift 0.12.0 on the classpath, transport setup dies 
with a
+      // NoClassDefFoundError (the Hive 2.3.10 jars need 0.14.1) instead of an 
SQLException.
 
       // mode = 'complete' routes to the countRecords overload that declares 
its connection as
       // `var conn: Connection = null` and closes it in an unguarded `finally 
{ conn.close() }`.
@@ -226,7 +234,7 @@ class TestValidateHoodieSyncProcedure extends 
HoodieSparkProcedureTestBase {
       val completeFailure = intercept[Throwable] {
         spark.sql(
           s"""call sync_validate(src_table => '$tableName', dst_table => 
'$tableName',
-             | mode => 'complete', hive_server_url => 'jdbc:hive2://unused', 
hive_pass => 'x')"""
+             | mode => 'complete', hive_server_url => 'jdbc:hive2://:10000', 
hive_pass => 'x')"""
             .stripMargin).collect()
       }
       // Assert over the cause chain, never the top-level type: on Spark 3.4+ 
QueryExecution wraps a
@@ -244,7 +252,7 @@ class TestValidateHoodieSyncProcedure extends 
HoodieSparkProcedureTestBase {
       val latestPartitionsFailure = intercept[Throwable] {
         spark.sql(
           s"""call sync_validate(src_table => '$tableName', dst_table => 
'$tableName',
-             | mode => 'latestPartitions', hive_server_url => 
'jdbc:hive2://unused', hive_pass => 'x')"""
+             | mode => 'latestPartitions', hive_server_url => 
'jdbc:hive2://:10000', hive_pass => 'x')"""
             .stripMargin).collect()
       }
       
assert(causeChain(latestPartitionsFailure).exists(_.isInstanceOf[SQLException]),

Reply via email to