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

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


The following commit(s) were added to refs/heads/master by this push:
     new c081ccd0d7 [spark] Compile the shared Spark test sources against 4.0.3 
for paimon-spark-4.0 (#9794)
c081ccd0d7 is described below

commit c081ccd0d7003ceae2517c6b592a947e824acc25
Author: YangJie <[email protected]>
AuthorDate: Sun Sep 13 22:57:58 2026 -0400

    [spark] Compile the shared Spark test sources against 4.0.3 for 
paimon-spark-4.0 (#9794)
---
 .github/workflows/publish-snapshot-spark4.yml      |   2 +-
 paimon-spark/paimon-spark-4.0/pom.xml              |   6 +-
 .../StreamTestCheckAnswerWithTimeoutStub.scala     |  63 -------
 .../pom.xml                                        | 184 +++++++++++----------
 pom.xml                                            |   1 +
 5 files changed, 103 insertions(+), 153 deletions(-)

diff --git a/.github/workflows/publish-snapshot-spark4.yml 
b/.github/workflows/publish-snapshot-spark4.yml
index c1b8eabeb0..998375b300 100644
--- a/.github/workflows/publish-snapshot-spark4.yml
+++ b/.github/workflows/publish-snapshot-spark4.yml
@@ -69,6 +69,6 @@ jobs:
         
           mvn --settings $tmp_settings -ntp clean install -Dgpg.skip 
-Drat.skip -DskipTests -Papache-release,spark4,flink1 -pl 
org.apache.paimon:paimon-spark-4.0_2.13,org.apache.paimon:paimon-spark-4.1_2.13 
-am
           # skip deploy paimon-spark-common_2.13 since they are already 
deployed in publish-snapshot.yml
-          mvn --settings $tmp_settings -ntp clean deploy -Dgpg.skip -Drat.skip 
-DskipTests -Papache-release,spark4,flink1 -pl 
org.apache.paimon:paimon-spark4-common_2.13,org.apache.paimon:paimon-spark-ut_2.13,org.apache.paimon:paimon-spark-4.0_2.13,org.apache.paimon:paimon-spark-4.1_2.13
+          mvn --settings $tmp_settings -ntp clean deploy -Dgpg.skip -Drat.skip 
-DskipTests -Papache-release,spark4,flink1 -pl 
org.apache.paimon:paimon-spark4-common_2.13,org.apache.paimon:paimon-spark-ut_2.13,org.apache.paimon:paimon-spark-ut-4.0_2.13,org.apache.paimon:paimon-spark-4.0_2.13,org.apache.paimon:paimon-spark-4.1_2.13
 
           rm $tmp_settings
diff --git a/paimon-spark/paimon-spark-4.0/pom.xml 
b/paimon-spark/paimon-spark-4.0/pom.xml
index d84e6e3ae9..1a0f80701d 100644
--- a/paimon-spark/paimon-spark-4.0/pom.xml
+++ b/paimon-spark/paimon-spark-4.0/pom.xml
@@ -124,9 +124,13 @@ under the License.
 
         <!-- test -->
 
+        <!-- The 4.0-compiled build of `paimon-spark-ut`'s test sources. The 
baseline build cannot be
+             used here: it is compiled against the `spark4` profile baseline, 
so its classfiles can
+             reference Spark symbols that a 4.0 runtime does not have. See
+             `paimon-spark-ut-4.0/pom.xml`. -->
         <dependency>
             <groupId>org.apache.paimon</groupId>
-            <artifactId>paimon-spark-ut_${scala.binary.version}</artifactId>
+            
<artifactId>paimon-spark-ut-4.0_${scala.binary.version}</artifactId>
             <version>${project.version}</version>
             <classifier>tests</classifier>
             <scope>test</scope>
diff --git 
a/paimon-spark/paimon-spark-4.0/src/test/scala/org/apache/spark/sql/streaming/StreamTestCheckAnswerWithTimeoutStub.scala
 
b/paimon-spark/paimon-spark-4.0/src/test/scala/org/apache/spark/sql/streaming/StreamTestCheckAnswerWithTimeoutStub.scala
deleted file mode 100644
index bb6edfa9ae..0000000000
--- 
a/paimon-spark/paimon-spark-4.0/src/test/scala/org/apache/spark/sql/streaming/StreamTestCheckAnswerWithTimeoutStub.scala
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.spark.sql.streaming
-
-/**
- * Test-scope stubs for Spark 4.1-only `StreamTest` inner classes.
- *
- * Spark 4.1 added several `CheckAnswer` / `WaitUntil` helpers inside 
`StreamTest`; Paimon's shared
- * test base classes in `paimon-spark-ut` mix in `StreamTest` and are compiled 
against Spark 4.1.1
- * (the default `spark.version` under the `spark4` profile), so their compiled 
bytecode has
- * constant-pool references to the nested companion objects.
- *
- * When those test classes are loaded on a Spark 4.0.2 runtime (the 
paimon-spark-4.0 test suite),
- * `junit-vintage`'s discovery phase tries to verify each class and fails to 
link the missing 4.1
- * symbols, crashing the engine before any Paimon test can run. No Paimon test 
actually invokes
- * these helpers — the references only exist in the constant pool from 
trait-mix-in synthetic
- * forwarders — so empty class files with the matching names are enough to 
satisfy the verifier.
- *
- * Diffing `spark-sql_2.13-4.1.1-tests.jar` against 
`spark-sql_2.13-4.0.1-tests.jar` shows the
- * following `StreamTest$…` classes are 4.1-only:
- *
- * companion objects (always referenced via MODULE$ access):
- *   - `StreamTest$CheckAnswerWithTimeout$`
- *   - `StreamTest$CheckAnswerRowsContainsWithTimeout$`
- *   - `StreamTest$CheckAnswerRowsNoWait$`
- *   - `StreamTest$WaitUntilBatchProcessed$`
- *   - `StreamTest$WaitUntilCurrentBatchProcessed$`
- *
- * case classes (may be referenced as parameter / return types):
- *   - `StreamTest$CheckAnswerRowsContainsWithTimeout`
- *   - `StreamTest$CheckAnswerRowsNoWait`
- *   - `StreamTest$WaitUntilBatchProcessed`
- *
- * Scala's backtick syntax lets us declare classes whose compiled names 
contain `$`, so each stub
- * compiles to exactly the file name expected by the verifier. They live in 
`src/test/scala/` so
- * they are never packaged into any production jar (including the 
paimon-spark-4.0 shaded artifact)
- * and do not leak onto Spark 4.1 classpaths where the real symbols must win.
- */
-private[streaming] class `StreamTest$CheckAnswerWithTimeout$`
-private[streaming] class `StreamTest$CheckAnswerRowsContainsWithTimeout$`
-private[streaming] class `StreamTest$CheckAnswerRowsNoWait$`
-private[streaming] class `StreamTest$WaitUntilBatchProcessed$`
-private[streaming] class `StreamTest$WaitUntilCurrentBatchProcessed$`
-
-private[streaming] class `StreamTest$CheckAnswerRowsContainsWithTimeout`
-private[streaming] class `StreamTest$CheckAnswerRowsNoWait`
-private[streaming] class `StreamTest$WaitUntilBatchProcessed`
diff --git a/paimon-spark/paimon-spark-4.0/pom.xml 
b/paimon-spark/paimon-spark-ut-4.0/pom.xml
similarity index 52%
copy from paimon-spark/paimon-spark-4.0/pom.xml
copy to paimon-spark/paimon-spark-ut-4.0/pom.xml
index d84e6e3ae9..b4a96db574 100644
--- a/paimon-spark/paimon-spark-4.0/pom.xml
+++ b/paimon-spark/paimon-spark-ut-4.0/pom.xml
@@ -28,23 +28,49 @@ under the License.
         <version>2.2-SNAPSHOT</version>
     </parent>
 
-    <artifactId>paimon-spark-4.0_2.13</artifactId>
-    <name>Paimon : Spark : 4.0 : 2.13</name>
-
+    <artifactId>paimon-spark-ut-4.0_${scala.binary.version}</artifactId>
+    <name>Paimon : Spark : UT : 4.0 : ${scala.binary.version}</name>
+
+    <!--
+      A second compilation of `paimon-spark-ut`'s test sources, against Spark 
4.0.3 instead of the
+      `spark4` profile baseline. Owns no sources of its own: `build-helper` 
adds
+      `../paimon-spark-ut/src/test/scala` and `src/test/java` as test-source 
roots, and
+      `<testResources>` points at that module's test resources, so there is 
exactly one copy of every
+      test to maintain.
+
+      Why a whole module rather than a second classifier on `paimon-spark-ut`: 
a Maven module has one
+      dependency set, so producing two artifacts compiled against different 
Spark versions from one
+      module is not expressible.
+
+      Why it is needed at all: `paimon-spark-4.0` used to consume 
`paimon-spark-ut`'s test-jar, which
+      is compiled against the baseline. Those classfiles reference Spark 
symbols that a 4.0 runtime
+      cannot resolve, which is what `StreamTestCheckAnswerWithTimeoutStub` 
stood in for. Compiling
+      the same sources against 4.0.3 cannot emit a reference to a symbol 4.0.3 
does not have, so the
+      stub is deleted here.
+
+      Serves `paimon-spark-4.0` only: `paimon-spark-4.1` pins 4.1.2, which is 
the baseline, so the
+      baseline build already matches its runtime and it keeps consuming 
`paimon-spark-ut` directly.
+    -->
     <properties>
         <spark.version>4.0.3</spark.version>
-        <!-- Spark 4.x uses SLF4J 2.x (`org.slf4j.spi.LoggingEventBuilder` is 
2.x-only). Override
-             the Paimon parent pom's default `slf4j.version=1.7.32` so the 
classpath is uniformly
-             2.x; otherwise `log4j-slf4j2-impl` + `slf4j-api:1.7.32` mix 
produces
-             `NoClassDefFoundError: org/slf4j/spi/LoggingEventBuilder` at test 
startup. -->
-        <slf4j.version>2.0.16</slf4j.version>
+        <ut.module.dir>${project.basedir}/../paimon-spark-ut</ut.module.dir>
         <!-- Spark 4 only supports Scala 2.13. Pin it locally so this _2.13 
module resolves its
              dependencies to _2.13 even when the spark4 profile is inactive 
(see issue #6682);
              otherwise it inherits scala.binary.version=2.12 from 
paimon-parent. -->
         <scala.binary.version>2.13</scala.binary.version>
+        <!-- The tests belong to `paimon-spark-ut`, which runs them against 
the baseline. This module
+             exists only to produce a 4.0-compiled test-jar, so nothing should 
run them a second time
+             here. Both surefire and scalatest-maven-plugin bind their 
`skipTests` parameter to this
+             property; `maven.test.skip` would also skip test compilation and 
leave the test-jar
+             empty. Without this, surefire inherits the root pom's 
`default-test` and
+             `integration-tests` executions and fails on `TestLoggerExtension` 
with
+             `NoClassDefFoundError: org/slf4j/spi/LoggingEventBuilder`. -->
+        <skipTests>true</skipTests>
     </properties>
 
     <dependencies>
+        <!-- Add to the beginning, just to make IDEA prioritize loading 
Paimon's conflicting classes,
+             such as Parquet and ORC. Remove this once IDEA's bug is fixed. -->
         <dependency>
             <groupId>org.apache.paimon</groupId>
             <artifactId>paimon-format</artifactId>
@@ -52,31 +78,24 @@ under the License.
 
         <dependency>
             <groupId>org.apache.paimon</groupId>
-            
<artifactId>paimon-spark4-common_${scala.binary.version}</artifactId>
-            <version>${project.version}</version>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.paimon</groupId>
-            
<artifactId>paimon-spark-common_${scala.binary.version}</artifactId>
+            <artifactId>${paimon-sparkx-common}</artifactId>
             <version>${project.version}</version>
         </dependency>
 
         <!--
-          `paimon-spark4-common` transitively pulls in `spark-sql-api` at the 
version set by
-          `paimon-spark-common.spark.version` (4.1.2 under the `spark4` 
profile). Spark 4.1's
-          `SqlApiConf` added abstract `manageParserCaches()`, which Spark 
4.0's concrete
-          anonymous subclasses (e.g. `WithTestConf$$anon$4`) don't implement. 
Mixing those
-          jars produces `AbstractMethodError` at parser configuration time. Pin
-          `spark-sql-api` to `${spark.version}` (4.0.3) so the test classpath 
is uniformly 4.0.
+          `${paimon-sparkx-common}` transitively pulls in `spark-sql-api` at 
the `spark4` profile
+          baseline (4.1.2), so every Spark artifact is pinned to 
${spark.version} here to keep the
+          whole compile classpath on 4.0. Same reasoning as 
`paimon-spark-4.0`, and the same
+          `spark-connect-shims` exclusion on `spark-sql-api` and `spark-sql`: 
Spark 4.0.3's shims jar
+          carries a stub `org.apache.spark.SparkConf` with only `getAll()`, 
which scalac resolves in
+          preference to spark-core's real one, failing with `value set is not 
a member of
+          org.apache.spark.SparkConf`.
         -->
         <dependency>
             <groupId>org.apache.spark</groupId>
             <artifactId>spark-sql-api_${scala.binary.version}</artifactId>
             <version>${spark.version}</version>
             <exclusions>
-                <!-- See spark-sql exclusion below: spark-connect-shims ships 
a stub SparkConf
-                     that shadows the real one from spark-core. -->
                 <exclusion>
                     <groupId>org.apache.spark</groupId>
                     
<artifactId>spark-connect-shims_${scala.binary.version}</artifactId>
@@ -89,14 +108,6 @@ under the License.
             <artifactId>spark-sql_${scala.binary.version}</artifactId>
             <version>${spark.version}</version>
             <exclusions>
-                <!--
-                  Spark 4.0.3 ships a tiny `spark-connect-shims` jar 
containing a stub
-                  `org.apache.spark.SparkConf` with only `getAll()` and a 
no-arg constructor
-                  (no `set` etc.). scalac resolves that stub in preference to 
spark-core's
-                  real `SparkConf` and fails compile with `value set is not a 
member of
-                  org.apache.spark.SparkConf`. The shims jar is only relevant 
to Spark Connect
-                  clients; excluding it leaves the full `SparkConf` from 
`spark-core`.
-                -->
                 <exclusion>
                     <groupId>org.apache.spark</groupId>
                     
<artifactId>spark-connect-shims_${scala.binary.version}</artifactId>
@@ -104,12 +115,6 @@ under the License.
             </exclusions>
         </dependency>
 
-        <dependency>
-            <groupId>org.apache.spark</groupId>
-            <artifactId>spark-core_${scala.binary.version}</artifactId>
-            <version>${spark.version}</version>
-        </dependency>
-
         <dependency>
             <groupId>org.apache.spark</groupId>
             <artifactId>spark-catalyst_${scala.binary.version}</artifactId>
@@ -118,103 +123,106 @@ under the License.
 
         <dependency>
             <groupId>org.apache.spark</groupId>
-            <artifactId>spark-hive_${scala.binary.version}</artifactId>
+            <artifactId>spark-core_${scala.binary.version}</artifactId>
             <version>${spark.version}</version>
         </dependency>
 
-        <!-- test -->
+        <!-- Below are test dependencies which need to be distinguished for 
different Spark versions. -->
 
         <dependency>
-            <groupId>org.apache.paimon</groupId>
-            <artifactId>paimon-spark-ut_${scala.binary.version}</artifactId>
-            <version>${project.version}</version>
+            <groupId>org.apache.spark</groupId>
+            <artifactId>spark-sql_${scala.binary.version}</artifactId>
+            <version>${spark.version}</version>
             <classifier>tests</classifier>
             <scope>test</scope>
-            <exclusions>
-                <exclusion>
-                    <groupId>*</groupId>
-                    <artifactId>*</artifactId>
-                </exclusion>
-            </exclusions>
         </dependency>
 
         <dependency>
-            <groupId>org.apache.paimon</groupId>
-            
<artifactId>paimon-spark4-common_${scala.binary.version}</artifactId>
-            <version>${project.version}</version>
+            <groupId>org.apache.spark</groupId>
+            <artifactId>spark-catalyst_${scala.binary.version}</artifactId>
+            <version>${spark.version}</version>
             <classifier>tests</classifier>
             <scope>test</scope>
-            <exclusions>
-                <exclusion>
-                    <groupId>*</groupId>
-                    <artifactId>*</artifactId>
-                </exclusion>
-            </exclusions>
         </dependency>
 
         <dependency>
             <groupId>org.apache.spark</groupId>
-            <artifactId>spark-sql_${scala.binary.version}</artifactId>
+            <artifactId>spark-core_${scala.binary.version}</artifactId>
             <version>${spark.version}</version>
             <classifier>tests</classifier>
             <scope>test</scope>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.apache.spark</groupId>
-                    
<artifactId>spark-connect-shims_${scala.binary.version}</artifactId>
-                </exclusion>
-            </exclusions>
         </dependency>
 
         <dependency>
             <groupId>org.apache.spark</groupId>
-            <artifactId>spark-catalyst_${scala.binary.version}</artifactId>
+            <artifactId>spark-hive_${scala.binary.version}</artifactId>
             <version>${spark.version}</version>
-            <classifier>tests</classifier>
             <scope>test</scope>
         </dependency>
 
         <dependency>
             <groupId>org.apache.spark</groupId>
-            <artifactId>spark-core_${scala.binary.version}</artifactId>
+            <artifactId>spark-avro_${scala.binary.version}</artifactId>
             <version>${spark.version}</version>
-            <classifier>tests</classifier>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.paimon</groupId>
+            <artifactId>paimon-lumina</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+            <version>${mockito.version}</version>
             <scope>test</scope>
         </dependency>
     </dependencies>
 
     <build>
+        <testResources>
+            <testResource>
+                <directory>${ut.module.dir}/src/test/resources</directory>
+            </testResource>
+        </testResources>
+
         <plugins>
             <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-shade-plugin</artifactId>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>build-helper-maven-plugin</artifactId>
                 <executions>
                     <execution>
-                        <id>shade-paimon</id>
-                        <phase>package</phase>
+                        <id>add-ut-test-sources</id>
+                        <phase>generate-test-sources</phase>
                         <goals>
-                            <goal>shade</goal>
+                            <goal>add-test-source</goal>
                         </goals>
                         <configuration>
-                            <filters>
-                                <filter>
-                                    <artifact>*</artifact>
-                                    <excludes>
-                                        
<exclude>com/github/luben/zstd/**</exclude>
-                                        <exclude>**/*libzstd-jni-*.so</exclude>
-                                        
<exclude>**/*libzstd-jni-*.dll</exclude>
-                                    </excludes>
-                                </filter>
-                            </filters>
-                            <artifactSet>
-                                <includes combine.children="append">
-                                     
<include>org.apache.paimon:paimon-spark4-common_${scala.binary.version}</include>
-                                </includes>
-                            </artifactSet>
+                            <sources>
+                                
<source>${ut.module.dir}/src/test/scala</source>
+                                <source>${ut.module.dir}/src/test/java</source>
+                            </sources>
                         </configuration>
                     </execution>
                 </executions>
             </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>prepare-test-jar</id>
+                        <phase>test-compile</phase>
+                        <goals>
+                            <goal>test-jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
         </plugins>
     </build>
 </project>
diff --git a/pom.xml b/pom.xml
index f4d2c5b1da..0b5512bd31 100644
--- a/pom.xml
+++ b/pom.xml
@@ -429,6 +429,7 @@ under the License.
             <id>spark4</id>
             <modules>
                 <module>paimon-spark/paimon-spark4-common</module>
+                <module>paimon-spark/paimon-spark-ut-4.0</module>
                 <module>paimon-spark/paimon-spark-4.0</module>
                 <module>paimon-spark/paimon-spark-4.1</module>
             </modules>

Reply via email to