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

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


The following commit(s) were added to refs/heads/master by this push:
     new 622106923e0 [FLINK-40382][tests] Execute static nested test class 
variants and guard against regressions
622106923e0 is described below

commit 622106923e09b76c3e3d13624b3e7bbb83cc1d73
Author: Purushottam Sinha <[email protected]>
AuthorDate: Tue Sep 1 00:33:05 2026 +0530

    [FLINK-40382][tests] Execute static nested test class variants and guard 
against regressions
---
 .../architecture/TestCodeArchitectureTestBase.java |   4 +
 .../architecture/rules/NestedTestClassRules.java   |  92 ++++
 .../typeutils/runtime/EitherSerializerTest.java    |   2 -
 .../typeutils/runtime/NullableSerializerTest.java  | 102 +++--
 .../fs/azurefs/AzureFileSystemBehaviorITCase.java  | 279 ++++++------
 .../python/ArrayDataSerializerTest.java            |  11 +-
 .../api/operators/InputSelectionTest.java          |   4 +-
 .../runtime/typeutils/ExternalSerializerTest.java  |  73 +--
 .../runtime/typeutils/RowDataSerializerTest.java   | 496 ++++++++++-----------
 .../typeutils/TimestampDataSerializerTest.java     |  74 +--
 .../TypeSerializerTestCoverageTest.java            |   2 +
 11 files changed, 643 insertions(+), 496 deletions(-)

diff --git 
a/flink-architecture-tests/flink-architecture-tests-test/src/main/java/org/apache/flink/architecture/TestCodeArchitectureTestBase.java
 
b/flink-architecture-tests/flink-architecture-tests-test/src/main/java/org/apache/flink/architecture/TestCodeArchitectureTestBase.java
index 9b7984d002b..ccee0cedd31 100644
--- 
a/flink-architecture-tests/flink-architecture-tests-test/src/main/java/org/apache/flink/architecture/TestCodeArchitectureTestBase.java
+++ 
b/flink-architecture-tests/flink-architecture-tests-test/src/main/java/org/apache/flink/architecture/TestCodeArchitectureTestBase.java
@@ -19,6 +19,7 @@
 package org.apache.flink.architecture;
 
 import org.apache.flink.architecture.rules.ITCaseRules;
+import org.apache.flink.architecture.rules.NestedTestClassRules;
 import org.apache.flink.architecture.rules.TestNamingRules;
 
 import com.tngtech.archunit.junit.ArchTest;
@@ -36,4 +37,7 @@ public class TestCodeArchitectureTestBase {
     @ArchTest public static final ArchTests ITCASE = 
ArchTests.in(ITCaseRules.class);
 
     @ArchTest public static final ArchTests TEST_NAMING = 
ArchTests.in(TestNamingRules.class);
+
+    @ArchTest
+    public static final ArchTests NESTED_TEST_CLASS = 
ArchTests.in(NestedTestClassRules.class);
 }
diff --git 
a/flink-architecture-tests/flink-architecture-tests-test/src/main/java/org/apache/flink/architecture/rules/NestedTestClassRules.java
 
b/flink-architecture-tests/flink-architecture-tests-test/src/main/java/org/apache/flink/architecture/rules/NestedTestClassRules.java
new file mode 100644
index 00000000000..31fc9367942
--- /dev/null
+++ 
b/flink-architecture-tests/flink-architecture-tests-test/src/main/java/org/apache/flink/architecture/rules/NestedTestClassRules.java
@@ -0,0 +1,92 @@
+/*
+ * 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.flink.architecture.rules;
+
+import com.tngtech.archunit.base.DescribedPredicate;
+import com.tngtech.archunit.core.domain.JavaClass;
+import com.tngtech.archunit.junit.ArchTest;
+import com.tngtech.archunit.lang.ArchRule;
+import org.junit.jupiter.api.Nested;
+
+import java.util.List;
+
+import static com.tngtech.archunit.core.domain.JavaModifier.ABSTRACT;
+import static com.tngtech.archunit.core.domain.JavaModifier.PRIVATE;
+import static 
org.apache.flink.architecture.common.GivenJavaClasses.javaClassesThat;
+
+/** Rules catching test classes that surefire and JUnit both silently skip 
when nested. */
+public class NestedTestClassRules {
+
+    private static final List<String> TEST_METHOD_ANNOTATIONS =
+            List.of(
+                    "org.junit.jupiter.api.Test",
+                    "org.junit.jupiter.api.TestTemplate",
+                    "org.junit.jupiter.api.RepeatedTest",
+                    "org.junit.jupiter.api.TestFactory",
+                    "org.junit.jupiter.params.ParameterizedTest");
+
+    // includes inherited methods, e.g. a variant that only extends a base
+    private static final DescribedPredicate<JavaClass> 
ARE_EXECUTABLE_TEST_CLASSES =
+            DescribedPredicate.describe(
+                    "are executable JUnit test classes",
+                    clazz ->
+                            clazz.getAllMethods().stream()
+                                    .anyMatch(
+                                            method ->
+                                                    
TEST_METHOD_ANNOTATIONS.stream()
+                                                            
.anyMatch(method::isAnnotatedWith)));
+
+    // excludes manually-driven helpers (e.g. a SerializerTestInstance built 
with real
+    // constructor args) that can never become @Nested regardless of 
static/inner shape
+    private static final DescribedPredicate<JavaClass> HAS_NO_ARG_CONSTRUCTOR =
+            DescribedPredicate.describe(
+                    "declare a no-arg constructor",
+                    clazz ->
+                            clazz.getConstructors().stream()
+                                    .anyMatch(
+                                            constructor ->
+                                                    
constructor.getRawParameterTypes().isEmpty()));
+
+    @ArchTest
+    public static final ArchRule 
STATIC_NESTED_TEST_CLASSES_SHOULD_BE_INNER_CLASSES =
+            javaClassesThat()
+                    .areMemberClasses()
+                    .and()
+                    .doNotHaveModifier(ABSTRACT)
+                    .and(ARE_EXECUTABLE_TEST_CLASSES)
+                    .and(HAS_NO_ARG_CONSTRUCTOR)
+                    .should()
+                    .beInnerClasses()
+                    // not every module has nested test classes
+                    .allowEmptyShould(true)
+                    .as(
+                            "A concrete nested test class must be a non-static 
inner class "
+                                    + "(annotated with @Nested), or surefire 
and JUnit both "
+                                    + "silently skip it. Abstract static bases 
are unaffected.");
+
+    @ArchTest
+    public static final ArchRule NESTED_TEST_CLASSES_SHOULD_NOT_BE_PRIVATE =
+            javaClassesThat()
+                    .areAnnotatedWith(Nested.class)
+                    .should()
+                    .notHaveModifier(PRIVATE)
+                    // not every module has @Nested test classes
+                    .allowEmptyShould(true)
+                    .as("A @Nested test class must not be private; JUnit 
cannot instantiate it");
+}
diff --git 
a/flink-core/src/test/java/org/apache/flink/api/java/typeutils/runtime/EitherSerializerTest.java
 
b/flink-core/src/test/java/org/apache/flink/api/java/typeutils/runtime/EitherSerializerTest.java
index 606d98637f1..56086c8f6b1 100644
--- 
a/flink-core/src/test/java/org/apache/flink/api/java/typeutils/runtime/EitherSerializerTest.java
+++ 
b/flink-core/src/test/java/org/apache/flink/api/java/typeutils/runtime/EitherSerializerTest.java
@@ -33,7 +33,6 @@ import org.apache.flink.types.Either;
 import org.apache.flink.types.LongValue;
 import org.apache.flink.types.StringValue;
 
-import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 
 import java.io.IOException;
@@ -223,7 +222,6 @@ class EitherSerializerTest {
      * that the type of the created instance is the same as the type class 
parameter. Since we
      * arbitrarily create always create a Left instance we override this test.
      */
-    @Nested
     private class EitherSerializerTestInstance<T> extends 
SerializerTestInstance<T> {
 
         public EitherSerializerTestInstance(
diff --git 
a/flink-core/src/test/java/org/apache/flink/api/java/typeutils/runtime/NullableSerializerTest.java
 
b/flink-core/src/test/java/org/apache/flink/api/java/typeutils/runtime/NullableSerializerTest.java
index 9726dcc495e..222899ff0d3 100644
--- 
a/flink-core/src/test/java/org/apache/flink/api/java/typeutils/runtime/NullableSerializerTest.java
+++ 
b/flink-core/src/test/java/org/apache/flink/api/java/typeutils/runtime/NullableSerializerTest.java
@@ -24,76 +24,82 @@ import 
org.apache.flink.api.common.typeutils.base.IntSerializer;
 import org.apache.flink.api.common.typeutils.base.StringSerializer;
 
 import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
 /** Unit tests for {@link NullableSerializer}. */
-abstract class NullableSerializerTest extends SerializerTestBase<Integer> {
-    private static final TypeSerializer<Integer> originalSerializer = 
IntSerializer.INSTANCE;
+class NullableSerializerTest {
 
-    private TypeSerializer<Integer> nullableSerializer;
+    @Nested
+    final class NullableSerializerWithPaddingTest extends 
NullableSerializerTestBase {
 
-    @BeforeEach
-    void init() {
-        nullableSerializer =
-                NullableSerializer.wrapIfNullIsNotSupported(
-                        originalSerializer, isPaddingNullValue());
+        @Override
+        boolean isPaddingNullValue() {
+            return true;
+        }
     }
 
-    @Override
-    protected TypeSerializer<Integer> createSerializer() {
-        return NullableSerializer.wrapIfNullIsNotSupported(
-                originalSerializer, isPaddingNullValue());
-    }
+    @Nested
+    final class NullableSerializerWithoutPaddingTest extends 
NullableSerializerTestBase {
 
-    @Override
-    protected int getLength() {
-        return isPaddingNullValue() ? 5 : -1;
+        @Override
+        boolean isPaddingNullValue() {
+            return false;
+        }
     }
 
-    @Override
-    protected Class<Integer> getTypeClass() {
-        return Integer.class;
-    }
+    abstract static class NullableSerializerTestBase extends 
SerializerTestBase<Integer> {
+        private static final TypeSerializer<Integer> originalSerializer = 
IntSerializer.INSTANCE;
 
-    @Override
-    protected Integer[] getTestData() {
-        return new Integer[] {5, -1, null, 5};
-    }
+        private TypeSerializer<Integer> nullableSerializer;
 
-    @Test
-    void testWrappingNotNeeded() {
-        assertThat(
-                        NullableSerializer.wrapIfNullIsNotSupported(
-                                StringSerializer.INSTANCE, 
isPaddingNullValue()))
-                .isEqualTo(StringSerializer.INSTANCE);
-    }
+        @BeforeEach
+        void init() {
+            nullableSerializer =
+                    NullableSerializer.wrapIfNullIsNotSupported(
+                            originalSerializer, isPaddingNullValue());
+        }
 
-    @Test
-    void testWrappingNeeded() {
-        assertThat(nullableSerializer)
-                .isInstanceOf(NullableSerializer.class)
-                .isEqualTo(
-                        NullableSerializer.wrapIfNullIsNotSupported(
-                                nullableSerializer, isPaddingNullValue()));
-    }
+        @Override
+        protected TypeSerializer<Integer> createSerializer() {
+            return NullableSerializer.wrapIfNullIsNotSupported(
+                    originalSerializer, isPaddingNullValue());
+        }
 
-    abstract boolean isPaddingNullValue();
+        @Override
+        protected int getLength() {
+            return isPaddingNullValue() ? 5 : -1;
+        }
 
-    static final class NullableSerializerWithPaddingTest extends 
NullableSerializerTest {
+        @Override
+        protected Class<Integer> getTypeClass() {
+            return Integer.class;
+        }
 
         @Override
-        boolean isPaddingNullValue() {
-            return true;
+        protected Integer[] getTestData() {
+            return new Integer[] {5, -1, null, 5};
         }
-    }
 
-    static final class NullableSerializerWithoutPaddingTest extends 
NullableSerializerTest {
+        @Test
+        void testWrappingNotNeeded() {
+            assertThat(
+                            NullableSerializer.wrapIfNullIsNotSupported(
+                                    StringSerializer.INSTANCE, 
isPaddingNullValue()))
+                    .isEqualTo(StringSerializer.INSTANCE);
+        }
 
-        @Override
-        boolean isPaddingNullValue() {
-            return false;
+        @Test
+        void testWrappingNeeded() {
+            assertThat(nullableSerializer)
+                    .isInstanceOf(NullableSerializer.class)
+                    .isEqualTo(
+                            NullableSerializer.wrapIfNullIsNotSupported(
+                                    nullableSerializer, isPaddingNullValue()));
         }
+
+        abstract boolean isPaddingNullValue();
     }
 }
diff --git 
a/flink-filesystems/flink-azure-fs-hadoop/src/test/java/org/apache/flink/fs/azurefs/AzureFileSystemBehaviorITCase.java
 
b/flink-filesystems/flink-azure-fs-hadoop/src/test/java/org/apache/flink/fs/azurefs/AzureFileSystemBehaviorITCase.java
index 6830e29a670..ca982997e31 100644
--- 
a/flink-filesystems/flink-azure-fs-hadoop/src/test/java/org/apache/flink/fs/azurefs/AzureFileSystemBehaviorITCase.java
+++ 
b/flink-filesystems/flink-azure-fs-hadoop/src/test/java/org/apache/flink/fs/azurefs/AzureFileSystemBehaviorITCase.java
@@ -33,7 +33,9 @@ import com.microsoft.azure.credentials.AzureTokenCredentials;
 import com.microsoft.azure.management.Azure;
 import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInstance;
 
 import java.io.BufferedReader;
 import java.io.File;
@@ -48,27 +50,35 @@ import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assumptions.assumeThat;
 
 /** An implementation of the {@link FileSystemBehaviorTestSuite} for Azure 
based file system. */
-class AzureFileSystemBehaviorITCase extends FileSystemBehaviorTestSuite {
+class AzureFileSystemBehaviorITCase {
 
-    private static final String CONTAINER = 
System.getenv("ARTIFACTS_AZURE_CONTAINER");
-    private static final String ACCOUNT = 
System.getenv("ARTIFACTS_AZURE_STORAGE_ACCOUNT");
-    private static final String ACCESS_KEY = 
System.getenv("ARTIFACTS_AZURE_ACCESS_KEY");
-    private static final String RESOURCE_GROUP = 
System.getenv("ARTIFACTS_AZURE_RESOURCE_GROUP");
-    private static final String SUBSCRIPTION_ID = 
System.getenv("ARTIFACTS_AZURE_SUBSCRIPTION_ID");
-    private static final String TOKEN_CREDENTIALS_FILE =
-            System.getenv("ARTIFACTS_AZURE_TOKEN_CREDENTIALS_FILE");
-
-    private static final String TEST_DATA_DIR = "tests-" + UUID.randomUUID();
+    @Nested
+    class HttpsAzureFileSystemBehaviorITCase extends 
AzureFileSystemBehaviorITCaseBase {
+        @Override
+        protected Path getBasePath() {
+            // 
wasbs://[email protected]/testDataDir
+            String uriString =
+                    "wasbs://"
+                            + CONTAINER
+                            + '@'
+                            + ACCOUNT
+                            + ".blob.core.windows.net/"
+                            + TEST_DATA_DIR;
+            return new Path(uriString);
+        }
+    }
 
     /**
-     * Azure Blob Storage defaults to https only storage accounts, tested in 
the base class.
+     * Azure Blob Storage defaults to https only storage accounts, tested 
above.
      *
      * <p>This nested class repeats the tests with http support, but only if a 
best effort check on
      * https support succeeds.
      */
-    static class HttpSupportAzureFileSystemBehaviorITCase extends 
AzureFileSystemBehaviorITCase {
+    @Nested
+    @TestInstance(TestInstance.Lifecycle.PER_CLASS)
+    class HttpSupportAzureFileSystemBehaviorITCase extends 
AzureFileSystemBehaviorITCaseBase {
         @BeforeAll
-        static void onlyRunIfHttps() throws IOException {
+        void onlyRunIfHttps() throws IOException {
             // default to https only, as some fields are missing
             assumeThat(RESOURCE_GROUP)
                     .describedAs("Azure resource group not configured, 
skipping test...")
@@ -93,144 +103,151 @@ class AzureFileSystemBehaviorITCase extends 
FileSystemBehaviorTestSuite {
         }
     }
 
-    private static boolean isHttpsTrafficOnly() throws IOException {
-        AzureTokenCredentials credentials =
-                ApplicationTokenCredentials.fromFile(new 
File(TOKEN_CREDENTIALS_FILE));
-        Azure azure =
-                StringUtils.isNullOrWhitespaceOnly(SUBSCRIPTION_ID)
-                        ? 
Azure.authenticate(credentials).withDefaultSubscription()
-                        : 
Azure.authenticate(credentials).withSubscription(SUBSCRIPTION_ID);
-
-        return azure.storageAccounts()
-                .getByResourceGroup(RESOURCE_GROUP, ACCOUNT)
-                .inner()
-                .enableHttpsTrafficOnly();
-    }
+    abstract static class AzureFileSystemBehaviorITCaseBase extends 
FileSystemBehaviorTestSuite {
+
+        static final String CONTAINER = 
System.getenv("ARTIFACTS_AZURE_CONTAINER");
+        static final String ACCOUNT = 
System.getenv("ARTIFACTS_AZURE_STORAGE_ACCOUNT");
+        private static final String ACCESS_KEY = 
System.getenv("ARTIFACTS_AZURE_ACCESS_KEY");
+        static final String RESOURCE_GROUP = 
System.getenv("ARTIFACTS_AZURE_RESOURCE_GROUP");
+        private static final String SUBSCRIPTION_ID =
+                System.getenv("ARTIFACTS_AZURE_SUBSCRIPTION_ID");
+        static final String TOKEN_CREDENTIALS_FILE =
+                System.getenv("ARTIFACTS_AZURE_TOKEN_CREDENTIALS_FILE");
+
+        static final String TEST_DATA_DIR = "tests-" + UUID.randomUUID();
+
+        static boolean isHttpsTrafficOnly() throws IOException {
+            AzureTokenCredentials credentials =
+                    ApplicationTokenCredentials.fromFile(new 
File(TOKEN_CREDENTIALS_FILE));
+            Azure azure =
+                    StringUtils.isNullOrWhitespaceOnly(SUBSCRIPTION_ID)
+                            ? 
Azure.authenticate(credentials).withDefaultSubscription()
+                            : 
Azure.authenticate(credentials).withSubscription(SUBSCRIPTION_ID);
+
+            return azure.storageAccounts()
+                    .getByResourceGroup(RESOURCE_GROUP, ACCOUNT)
+                    .inner()
+                    .enableHttpsTrafficOnly();
+        }
 
-    @BeforeAll
-    static void checkCredentialsAndSetup() {
-        // check whether credentials and container details exist
-        assumeThat(ACCOUNT)
-                .describedAs("Azure storage account not configured, skipping 
test...")
-                .isNotBlank();
-        assumeThat(CONTAINER)
-                .describedAs("Azure container not configured, skipping 
test...")
-                .isNotBlank();
-        assumeThat(ACCESS_KEY)
-                .describedAs("Azure access key not configured, skipping 
test...")
-                .isNotBlank();
-
-        // initialize configuration with valid credentials
-        final Configuration conf = new Configuration();
-        // fs.azure.account.key.youraccount.blob.core.windows.net = ACCESS_KEY
-        conf.setString("fs.azure.account.key." + ACCOUNT + 
".blob.core.windows.net", ACCESS_KEY);
-        FileSystem.initialize(conf, null);
-    }
+        @BeforeAll
+        static void checkCredentialsAndSetup() {
+            // check whether credentials and container details exist
+            assumeThat(ACCOUNT)
+                    .describedAs("Azure storage account not configured, 
skipping test...")
+                    .isNotBlank();
+            assumeThat(CONTAINER)
+                    .describedAs("Azure container not configured, skipping 
test...")
+                    .isNotBlank();
+            assumeThat(ACCESS_KEY)
+                    .describedAs("Azure access key not configured, skipping 
test...")
+                    .isNotBlank();
 
-    @AfterAll
-    static void clearFsConfig() {
-        FileSystem.initialize(new Configuration(), null);
-    }
+            // initialize configuration with valid credentials
+            final Configuration conf = new Configuration();
+            // fs.azure.account.key.youraccount.blob.core.windows.net = 
ACCESS_KEY
+            conf.setString(
+                    "fs.azure.account.key." + ACCOUNT + 
".blob.core.windows.net", ACCESS_KEY);
+            FileSystem.initialize(conf, null);
+        }
 
-    @Override
-    protected FileSystem getFileSystem() throws Exception {
-        return getBasePath().getFileSystem();
-    }
+        @AfterAll
+        static void clearFsConfig() {
+            FileSystem.initialize(new Configuration(), null);
+        }
 
-    @Override
-    protected Path getBasePath() {
-        // wasbs://[email protected]/testDataDir
-        String uriString =
-                "wasbs://" + CONTAINER + '@' + ACCOUNT + 
".blob.core.windows.net/" + TEST_DATA_DIR;
-        return new Path(uriString);
-    }
+        @Override
+        protected FileSystem getFileSystem() throws Exception {
+            return getBasePath().getFileSystem();
+        }
 
-    @Override
-    protected FileSystemKind getFileSystemKind() {
-        return FileSystemKind.OBJECT_STORE;
-    }
+        @Override
+        protected FileSystemKind getFileSystemKind() {
+            return FileSystemKind.OBJECT_STORE;
+        }
 
-    @Test
-    void testSimpleFileWriteAndRead() throws Exception {
-        final long deadline = System.nanoTime() + 30_000_000_000L; // 30 secs
+        @Test
+        void testSimpleFileWriteAndRead() throws Exception {
+            final long deadline = System.nanoTime() + 30_000_000_000L; // 30 
secs
 
-        final String testLine = "Hello Upload!";
+            final String testLine = "Hello Upload!";
 
-        final Path path = new Path(getBasePath() + "/test.txt");
-        final FileSystem fs = path.getFileSystem();
+            final Path path = new Path(getBasePath() + "/test.txt");
+            final FileSystem fs = path.getFileSystem();
 
-        try {
-            try (FSDataOutputStream out = fs.create(path, 
FileSystem.WriteMode.OVERWRITE);
-                    OutputStreamWriter writer =
-                            new OutputStreamWriter(out, 
StandardCharsets.UTF_8)) {
-                writer.write(testLine);
-            }
+            try {
+                try (FSDataOutputStream out = fs.create(path, 
FileSystem.WriteMode.OVERWRITE);
+                        OutputStreamWriter writer =
+                                new OutputStreamWriter(out, 
StandardCharsets.UTF_8)) {
+                    writer.write(testLine);
+                }
 
-            // just in case, wait for the path to exist
-            checkPathEventualExistence(fs, path, true, deadline);
+                // just in case, wait for the path to exist
+                checkPathEventualExistence(fs, path, true, deadline);
 
-            try (FSDataInputStream in = fs.open(path);
-                    InputStreamReader ir = new InputStreamReader(in, 
StandardCharsets.UTF_8);
-                    BufferedReader reader = new BufferedReader(ir)) {
-                String line = reader.readLine();
-                assertThat(line).isEqualTo(testLine);
+                try (FSDataInputStream in = fs.open(path);
+                        InputStreamReader ir = new InputStreamReader(in, 
StandardCharsets.UTF_8);
+                        BufferedReader reader = new BufferedReader(ir)) {
+                    String line = reader.readLine();
+                    assertThat(line).isEqualTo(testLine);
+                }
+            } finally {
+                fs.delete(path, false);
             }
-        } finally {
-            fs.delete(path, false);
-        }
 
-        // now file must be gone
-        checkPathEventualExistence(fs, path, false, deadline);
-    }
-
-    @Test
-    void testDirectoryListing() throws Exception {
-        final long deadline = System.nanoTime() + 30_000_000_000L; // 30 secs
-
-        final Path directory = new Path(getBasePath() + "/testdir/");
-        final FileSystem fs = directory.getFileSystem();
-
-        // directory must not yet exist
-        assertThat(fs.exists(directory)).isFalse();
-
-        try {
-            // create directory
-            assertThat(fs.mkdirs(directory)).isTrue();
+            // now file must be gone
+            checkPathEventualExistence(fs, path, false, deadline);
+        }
 
-            checkPathEventualExistence(fs, directory, true, deadline);
+        @Test
+        void testDirectoryListing() throws Exception {
+            final long deadline = System.nanoTime() + 30_000_000_000L; // 30 
secs
+
+            final Path directory = new Path(getBasePath() + "/testdir/");
+            final FileSystem fs = directory.getFileSystem();
+
+            // directory must not yet exist
+            assertThat(fs.exists(directory)).isFalse();
+
+            try {
+                // create directory
+                assertThat(fs.mkdirs(directory)).isTrue();
+
+                checkPathEventualExistence(fs, directory, true, deadline);
+
+                // directory empty
+                assertThat(fs.listStatus(directory)).isEmpty();
+
+                // create some files
+                final int numFiles = 3;
+                for (int i = 0; i < numFiles; i++) {
+                    Path file = new Path(directory, "/file-" + i);
+                    try (FSDataOutputStream out = fs.create(file, 
FileSystem.WriteMode.OVERWRITE);
+                            OutputStreamWriter writer =
+                                    new OutputStreamWriter(out, 
StandardCharsets.UTF_8)) {
+                        writer.write("hello-" + i + "\n");
+                    }
+                    // just in case, wait for the file to exist (should then 
also be reflected in
+                    // the directory's file list below)
+                    checkPathEventualExistence(fs, file, true, deadline);
+                }
 
-            // directory empty
-            assertThat(fs.listStatus(directory)).isEmpty();
+                FileStatus[] files = fs.listStatus(directory);
+                assertThat(files).hasSize(3);
 
-            // create some files
-            final int numFiles = 3;
-            for (int i = 0; i < numFiles; i++) {
-                Path file = new Path(directory, "/file-" + i);
-                try (FSDataOutputStream out = fs.create(file, 
FileSystem.WriteMode.OVERWRITE);
-                        OutputStreamWriter writer =
-                                new OutputStreamWriter(out, 
StandardCharsets.UTF_8)) {
-                    writer.write("hello-" + i + "\n");
+                for (FileStatus status : files) {
+                    assertThat(status.isDir()).isFalse();
                 }
-                // just in case, wait for the file to exist (should then also 
be reflected in the
-                // directory's file list below)
-                checkPathEventualExistence(fs, file, true, deadline);
-            }
 
-            FileStatus[] files = fs.listStatus(directory);
-            assertThat(files).hasSize(3);
-
-            for (FileStatus status : files) {
-                assertThat(status.isDir()).isFalse();
+                // now that there are files, the directory must exist
+                assertThat(fs.exists(directory)).isTrue();
+            } finally {
+                // clean up
+                fs.delete(directory, true);
             }
 
-            // now that there are files, the directory must exist
-            assertThat(fs.exists(directory)).isTrue();
-        } finally {
-            // clean up
-            fs.delete(directory, true);
+            // now directory must be gone
+            checkPathEventualExistence(fs, directory, false, deadline);
         }
-
-        // now directory must be gone
-        checkPathEventualExistence(fs, directory, false, deadline);
     }
 }
diff --git 
a/flink-python/src/test/java/org/apache/flink/table/runtime/typeutils/serializers/python/ArrayDataSerializerTest.java
 
b/flink-python/src/test/java/org/apache/flink/table/runtime/typeutils/serializers/python/ArrayDataSerializerTest.java
index 825944f7070..9f9b0a7a778 100644
--- 
a/flink-python/src/test/java/org/apache/flink/table/runtime/typeutils/serializers/python/ArrayDataSerializerTest.java
+++ 
b/flink-python/src/test/java/org/apache/flink/table/runtime/typeutils/serializers/python/ArrayDataSerializerTest.java
@@ -29,11 +29,14 @@ import org.apache.flink.table.types.logical.ArrayType;
 import org.apache.flink.table.types.logical.BigIntType;
 import org.apache.flink.table.types.logical.IntType;
 
+import org.junit.jupiter.api.Nested;
+
 /** Test for {@link ArrayDataSerializer}. */
 class ArrayDataSerializerTest {
 
     /** Test for ArrayData with Primitive data type. */
-    static class BaseArrayWithPrimitiveTest extends 
SerializerTestBase<ArrayData> {
+    @Nested
+    class BaseArrayWithPrimitiveTest extends SerializerTestBase<ArrayData> {
         @Override
         protected TypeSerializer<ArrayData> createSerializer() {
             return new ArrayDataSerializer(new BigIntType(), 
LongSerializer.INSTANCE);
@@ -56,7 +59,8 @@ class ArrayDataSerializerTest {
     }
 
     /** Test for ArrayData with ArrayData data type. */
-    static class ArrayDataWithBinaryArrayTest extends 
SerializerTestBase<ArrayData> {
+    @Nested
+    class ArrayDataWithBinaryArrayTest extends SerializerTestBase<ArrayData> {
 
         @Override
         protected TypeSerializer<ArrayData> createSerializer() {
@@ -89,7 +93,8 @@ class ArrayDataSerializerTest {
     }
 
     /** Test for ArrayData with ArrayData data type. */
-    static class BaseArrayWithNullTest extends SerializerTestBase<ArrayData> {
+    @Nested
+    class BaseArrayWithNullTest extends SerializerTestBase<ArrayData> {
 
         @Override
         protected TypeSerializer<ArrayData> createSerializer() {
diff --git 
a/flink-runtime/src/test/java/org/apache/flink/streaming/api/operators/InputSelectionTest.java
 
b/flink-runtime/src/test/java/org/apache/flink/streaming/api/operators/InputSelectionTest.java
index 4f4850ea995..680ba289d10 100644
--- 
a/flink-runtime/src/test/java/org/apache/flink/streaming/api/operators/InputSelectionTest.java
+++ 
b/flink-runtime/src/test/java/org/apache/flink/streaming/api/operators/InputSelectionTest.java
@@ -19,6 +19,7 @@ package org.apache.flink.streaming.api.operators;
 
 import org.apache.flink.streaming.api.operators.InputSelection.Builder;
 
+import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 
 import static org.assertj.core.api.Assertions.assertThat;
@@ -138,7 +139,8 @@ class InputSelectionTest {
     }
 
     /** Tests for {@link Builder}. */
-    static class BuilderTest {
+    @Nested
+    class BuilderTest {
 
         @Test
         void testSelect() {
diff --git 
a/flink-table/flink-table-type-utils/src/test/java/org/apache/flink/table/runtime/typeutils/ExternalSerializerTest.java
 
b/flink-table/flink-table-type-utils/src/test/java/org/apache/flink/table/runtime/typeutils/ExternalSerializerTest.java
index e1d88f1322e..a3c8e2f9ae4 100644
--- 
a/flink-table/flink-table-type-utils/src/test/java/org/apache/flink/table/runtime/typeutils/ExternalSerializerTest.java
+++ 
b/flink-table/flink-table-type-utils/src/test/java/org/apache/flink/table/runtime/typeutils/ExternalSerializerTest.java
@@ -24,6 +24,8 @@ import org.apache.flink.table.api.DataTypes;
 import org.apache.flink.table.types.DataType;
 import org.apache.flink.types.Row;
 
+import org.junit.jupiter.api.Nested;
+
 import java.lang.reflect.Array;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -32,37 +34,24 @@ import java.util.List;
 import java.util.Objects;
 
 /** Tests for {@link ExternalSerializer}. */
-abstract class ExternalSerializerTest<T> extends SerializerTestInstance<T> {
-
-    @SuppressWarnings("unchecked")
-    ExternalSerializerTest(TestSpec<T> testSpec) {
-        super(
-                ExternalSerializer.of(testSpec.dataType),
-                (Class<T>) testSpec.dataType.getConversionClass(),
-                testSpec.length,
-                testSpec.instances.toArray(
-                        (T[]) 
Array.newInstance(testSpec.dataType.getConversionClass(), 0)));
-    }
-
-    @Override
-    protected boolean allowNullInstances(TypeSerializer<T> serializer) {
-        return true;
-    }
+class ExternalSerializerTest {
 
-    static final class ExternalSerializer1Test extends ExternalSerializerTest {
-        public ExternalSerializer1Test() {
+    @Nested
+    final class ExternalSerializer1Test extends 
ExternalSerializerTestBase<Integer> {
+        ExternalSerializer1Test() {
             super(
-                    TestSpec.forDataType(DataTypes.INT())
+                    TestSpec.<Integer>forDataType(DataTypes.INT())
                             .withLength(4)
                             .addInstance(18)
                             .addInstance(42));
         }
     }
 
-    static final class ExternalSerializer2Test extends ExternalSerializerTest {
-        public ExternalSerializer2Test() {
+    @Nested
+    final class ExternalSerializer2Test extends 
ExternalSerializerTestBase<Row> {
+        ExternalSerializer2Test() {
             super(
-                    TestSpec.forDataType(
+                    TestSpec.<Row>forDataType(
                                     DataTypes.ROW(
                                             DataTypes.FIELD("age", 
DataTypes.INT()),
                                             DataTypes.FIELD("name", 
DataTypes.STRING())))
@@ -71,10 +60,11 @@ abstract class ExternalSerializerTest<T> extends 
SerializerTestInstance<T> {
         }
     }
 
-    static final class ExternalSerializer3Test extends ExternalSerializerTest {
-        public ExternalSerializer3Test() {
+    @Nested
+    final class ExternalSerializer3Test extends 
ExternalSerializerTestBase<ImmutableTestPojo> {
+        ExternalSerializer3Test() {
             super(
-                    TestSpec.forDataType(
+                    TestSpec.<ImmutableTestPojo>forDataType(
                                     DataTypes.STRUCTURED(
                                             ImmutableTestPojo.class,
                                             DataTypes.FIELD("age", 
DataTypes.INT()),
@@ -84,10 +74,12 @@ abstract class ExternalSerializerTest<T> extends 
SerializerTestInstance<T> {
         }
     }
 
-    static final class ExternalSerializer4Test extends ExternalSerializerTest {
-        public ExternalSerializer4Test() {
+    @Nested
+    final class ExternalSerializer4Test
+            extends ExternalSerializerTestBase<List<ImmutableTestPojo>> {
+        ExternalSerializer4Test() {
             super(
-                    TestSpec.forDataType(
+                    TestSpec.<List<ImmutableTestPojo>>forDataType(
                                     DataTypes.ARRAY(
                                                     DataTypes.STRUCTURED(
                                                             
ImmutableTestPojo.class,
@@ -106,15 +98,34 @@ abstract class ExternalSerializerTest<T> extends 
SerializerTestInstance<T> {
         }
     }
 
-    static final class ExternalSerializer5Test extends ExternalSerializerTest {
-        public ExternalSerializer5Test() {
+    @Nested
+    final class ExternalSerializer5Test extends 
ExternalSerializerTestBase<Integer[]> {
+        ExternalSerializer5Test() {
             super(
-                    TestSpec.forDataType(DataTypes.ARRAY(DataTypes.INT()))
+                    
TestSpec.<Integer[]>forDataType(DataTypes.ARRAY(DataTypes.INT()))
                             .addInstance(new Integer[] {0, 1, null, 3})
                             .addInstance(new Integer[0]));
         }
     }
 
+    abstract static class ExternalSerializerTestBase<T> extends 
SerializerTestInstance<T> {
+
+        @SuppressWarnings("unchecked")
+        ExternalSerializerTestBase(TestSpec<T> testSpec) {
+            super(
+                    ExternalSerializer.of(testSpec.dataType),
+                    (Class<T>) testSpec.dataType.getConversionClass(),
+                    testSpec.length,
+                    testSpec.instances.toArray(
+                            (T[]) 
Array.newInstance(testSpec.dataType.getConversionClass(), 0)));
+        }
+
+        @Override
+        protected boolean allowNullInstances(TypeSerializer<T> serializer) {
+            return true;
+        }
+    }
+
     // 
--------------------------------------------------------------------------------------------
 
     private static class TestSpec<T> {
diff --git 
a/flink-table/flink-table-type-utils/src/test/java/org/apache/flink/table/runtime/typeutils/RowDataSerializerTest.java
 
b/flink-table/flink-table-type-utils/src/test/java/org/apache/flink/table/runtime/typeutils/RowDataSerializerTest.java
index 6d6379ed046..4035fc65d37 100644
--- 
a/flink-table/flink-table-type-utils/src/test/java/org/apache/flink/table/runtime/typeutils/RowDataSerializerTest.java
+++ 
b/flink-table/flink-table-type-utils/src/test/java/org/apache/flink/table/runtime/typeutils/RowDataSerializerTest.java
@@ -86,30 +86,6 @@ abstract class RowDataSerializerTest extends 
SerializerTestInstance<RowData> {
 
     // 
----------------------------------------------------------------------------------------------
 
-    private static BinaryArrayData createArray(int... ints) {
-        BinaryArrayData array = new BinaryArrayData();
-        BinaryArrayWriter writer = new BinaryArrayWriter(array, ints.length, 
4);
-        for (int i = 0; i < ints.length; i++) {
-            writer.writeInt(i, ints[i]);
-        }
-        writer.complete();
-        return array;
-    }
-
-    private static BinaryMapData createMap(int[] keys, int[] values) {
-        return BinaryMapData.valueOf(createArray(keys), createArray(values));
-    }
-
-    private static GenericRowData createRow(Object f0, Object f1, Object f2, 
Object f3, Object f4) {
-        GenericRowData row = new GenericRowData(5);
-        row.setField(0, f0);
-        row.setField(1, f1);
-        row.setField(2, f2);
-        row.setField(3, f3);
-        row.setField(4, f4);
-        return row;
-    }
-
     private static boolean deepEqualsRowData(
             RowData should,
             RowData is,
@@ -197,265 +173,289 @@ abstract class RowDataSerializerTest extends 
SerializerTestInstance<RowData> {
                     .isInstanceOf(IllegalArgumentException.class);
         }
     }
+}
 
-    /** Class used for concurrent testing with KryoSerializer. */
-    private static class WrappedString {
+final class SimpleRowDataSerializerTest extends RowDataSerializerTest {
+    SimpleRowDataSerializerTest() {
+        super(getRowSerializer(), getData());
+    }
 
-        private final String content;
+    private static RowData[] getData() {
+        GenericRowData row1 = new GenericRowData(2);
+        row1.setField(0, 1);
+        row1.setField(1, fromString("a"));
 
-        WrappedString(String content) {
-            this.content = content;
-        }
+        GenericRowData row2 = new GenericRowData(2);
+        row2.setField(0, 2);
+        row2.setField(1, null);
+
+        return new RowData[] {row1, row2};
     }
 
-    static final class SimpleRowDataSerializerTest extends 
RowDataSerializerTest {
-        public SimpleRowDataSerializerTest() {
-            super(getRowSerializer(), getData());
-        }
+    private static RowDataSerializer getRowSerializer() {
+        InternalTypeInfo<RowData> typeInfo =
+                InternalTypeInfo.ofFields(new IntType(), 
VarCharType.STRING_TYPE);
 
-        private static RowData[] getData() {
-            GenericRowData row1 = new GenericRowData(2);
-            row1.setField(0, 1);
-            row1.setField(1, fromString("a"));
+        return typeInfo.toRowSerializer();
+    }
+}
 
-            GenericRowData row2 = new GenericRowData(2);
-            row2.setField(0, 2);
-            row2.setField(1, null);
+final class LargeRowDataSerializerTest extends RowDataSerializerTest {
+    LargeRowDataSerializerTest() {
+        super(getRowSerializer(), getData());
+    }
 
-            return new RowData[] {row1, row2};
-        }
+    private static RowData[] getData() {
+        GenericRowData row = new GenericRowData(13);
+        row.setField(0, 2);
+        row.setField(1, null);
+        row.setField(3, null);
+        row.setField(4, null);
+        row.setField(5, null);
+        row.setField(6, null);
+        row.setField(7, null);
+        row.setField(8, null);
+        row.setField(9, null);
+        row.setField(10, null);
+        row.setField(11, null);
+        row.setField(12, fromString("Test"));
+
+        return new RowData[] {row};
+    }
 
-        private static RowDataSerializer getRowSerializer() {
-            InternalTypeInfo<RowData> typeInfo =
-                    InternalTypeInfo.ofFields(new IntType(), 
VarCharType.STRING_TYPE);
+    private static RowDataSerializer getRowSerializer() {
+        InternalTypeInfo<RowData> typeInfo =
+                InternalTypeInfo.ofFields(
+                        new IntType(),
+                        new IntType(),
+                        new IntType(),
+                        new IntType(),
+                        new IntType(),
+                        new IntType(),
+                        new IntType(),
+                        new IntType(),
+                        new IntType(),
+                        new IntType(),
+                        new IntType(),
+                        new IntType(),
+                        VarCharType.STRING_TYPE);
+
+        return typeInfo.toRowSerializer();
+    }
+}
 
-            return typeInfo.toRowSerializer();
-        }
+final class RowDataSerializerWithComplexTypesTest extends 
RowDataSerializerTest {
+    RowDataSerializerWithComplexTypesTest() {
+        super(getRowSerializer(), getData());
     }
 
-    static final class LargeRowDataSerializerTest extends 
RowDataSerializerTest {
-        public LargeRowDataSerializerTest() {
-            super(getRowSerializer(), getData());
+    private static BinaryArrayData createArray(int... ints) {
+        BinaryArrayData array = new BinaryArrayData();
+        BinaryArrayWriter writer = new BinaryArrayWriter(array, ints.length, 
4);
+        for (int i = 0; i < ints.length; i++) {
+            writer.writeInt(i, ints[i]);
         }
+        writer.complete();
+        return array;
+    }
 
-        private static RowData[] getData() {
-            GenericRowData row = new GenericRowData(13);
-            row.setField(0, 2);
-            row.setField(1, null);
-            row.setField(3, null);
-            row.setField(4, null);
-            row.setField(5, null);
-            row.setField(6, null);
-            row.setField(7, null);
-            row.setField(8, null);
-            row.setField(9, null);
-            row.setField(10, null);
-            row.setField(11, null);
-            row.setField(12, fromString("Test"));
-
-            return new RowData[] {row};
-        }
+    private static BinaryMapData createMap(int[] keys, int[] values) {
+        return BinaryMapData.valueOf(createArray(keys), createArray(values));
+    }
 
-        private static RowDataSerializer getRowSerializer() {
-            InternalTypeInfo<RowData> typeInfo =
-                    InternalTypeInfo.ofFields(
-                            new IntType(),
-                            new IntType(),
-                            new IntType(),
-                            new IntType(),
-                            new IntType(),
-                            new IntType(),
-                            new IntType(),
-                            new IntType(),
-                            new IntType(),
-                            new IntType(),
-                            new IntType(),
-                            new IntType(),
-                            VarCharType.STRING_TYPE);
-
-            return typeInfo.toRowSerializer();
-        }
+    private static GenericRowData createRow(Object f0, Object f1, Object f2, 
Object f3, Object f4) {
+        GenericRowData row = new GenericRowData(5);
+        row.setField(0, f0);
+        row.setField(1, f1);
+        row.setField(2, f2);
+        row.setField(3, f3);
+        row.setField(4, f4);
+        return row;
     }
 
-    static final class RowDataSerializerWithComplexTypesTest extends 
RowDataSerializerTest {
-        public RowDataSerializerWithComplexTypesTest() {
-            super(getRowSerializer(), getData());
-        }
+    private static RowData[] getData() {
+        return new GenericRowData[] {
+            createRow(null, null, null, null, null),
+            createRow(0, null, null, null, null),
+            createRow(0, 0.0, null, null, null),
+            createRow(0, 0.0, fromString("a"), null, null),
+            createRow(1, 0.0, fromString("a"), null, null),
+            createRow(1, 1.0, fromString("a"), null, null),
+            createRow(1, 1.0, fromString("b"), null, null),
+            createRow(
+                    1,
+                    1.0,
+                    fromString("b"),
+                    createArray(1),
+                    createMap(new int[] {1}, new int[] {1})),
+            createRow(
+                    1,
+                    1.0,
+                    fromString("b"),
+                    createArray(1, 2),
+                    createMap(new int[] {1, 4}, new int[] {1, 2})),
+            createRow(
+                    1,
+                    1.0,
+                    fromString("b"),
+                    createArray(1, 2, 3),
+                    createMap(new int[] {1, 5}, new int[] {1, 3})),
+            createRow(
+                    1,
+                    1.0,
+                    fromString("b"),
+                    createArray(1, 2, 3, 4),
+                    createMap(new int[] {1, 6}, new int[] {1, 4})),
+            createRow(
+                    1,
+                    1.0,
+                    fromString("b"),
+                    createArray(1, 2, 3, 4, 5),
+                    createMap(new int[] {1, 7}, new int[] {1, 5})),
+            createRow(
+                    1,
+                    1.0,
+                    fromString("b"),
+                    createArray(1, 2, 3, 4, 5, 6),
+                    createMap(new int[] {1, 8}, new int[] {1, 6}))
+        };
+    }
 
-        private static RowData[] getData() {
-            return new GenericRowData[] {
-                createRow(null, null, null, null, null),
-                createRow(0, null, null, null, null),
-                createRow(0, 0.0, null, null, null),
-                createRow(0, 0.0, fromString("a"), null, null),
-                createRow(1, 0.0, fromString("a"), null, null),
-                createRow(1, 1.0, fromString("a"), null, null),
-                createRow(1, 1.0, fromString("b"), null, null),
-                createRow(
-                        1,
-                        1.0,
-                        fromString("b"),
-                        createArray(1),
-                        createMap(new int[] {1}, new int[] {1})),
-                createRow(
-                        1,
-                        1.0,
-                        fromString("b"),
-                        createArray(1, 2),
-                        createMap(new int[] {1, 4}, new int[] {1, 2})),
-                createRow(
-                        1,
-                        1.0,
-                        fromString("b"),
-                        createArray(1, 2, 3),
-                        createMap(new int[] {1, 5}, new int[] {1, 3})),
-                createRow(
-                        1,
-                        1.0,
-                        fromString("b"),
-                        createArray(1, 2, 3, 4),
-                        createMap(new int[] {1, 6}, new int[] {1, 4})),
-                createRow(
-                        1,
-                        1.0,
-                        fromString("b"),
-                        createArray(1, 2, 3, 4, 5),
-                        createMap(new int[] {1, 7}, new int[] {1, 5})),
-                createRow(
-                        1,
-                        1.0,
-                        fromString("b"),
-                        createArray(1, 2, 3, 4, 5, 6),
-                        createMap(new int[] {1, 8}, new int[] {1, 6}))
-            };
-        }
+    private static RowDataSerializer getRowSerializer() {
+        InternalTypeInfo<RowData> typeInfo =
+                InternalTypeInfo.ofFields(
+                        new IntType(),
+                        new DoubleType(),
+                        VarCharType.STRING_TYPE,
+                        new ArrayType(new IntType()),
+                        new MapType(new IntType(), new IntType()));
 
-        private static RowDataSerializer getRowSerializer() {
-            InternalTypeInfo<RowData> typeInfo =
-                    InternalTypeInfo.ofFields(
-                            new IntType(),
-                            new DoubleType(),
-                            VarCharType.STRING_TYPE,
-                            new ArrayType(new IntType()),
-                            new MapType(new IntType(), new IntType()));
+        return typeInfo.toRowSerializer();
+    }
+}
 
-            return typeInfo.toRowSerializer();
-        }
+final class RowDataSerializerWithKryoTest extends RowDataSerializerTest {
+    RowDataSerializerWithKryoTest() {
+        super(getRowSerializer(), getData());
     }
 
-    static final class RowDataSerializerWithKryoTest extends 
RowDataSerializerTest {
-        public RowDataSerializerWithKryoTest() {
-            super(getRowSerializer(), getData());
-        }
+    private static RowData[] getData() {
+        GenericRowData row = new GenericRowData(1);
+        row.setField(0, RawValueData.fromObject(new WrappedString("a")));
 
-        private static RowData[] getData() {
-            GenericRowData row = new GenericRowData(1);
-            row.setField(0, RawValueData.fromObject(new WrappedString("a")));
+        return new RowData[] {row};
+    }
 
-            return new RowData[] {row};
-        }
+    private static RowDataSerializer getRowSerializer() {
+        RawValueDataSerializer<WrappedString> rawValueSerializer =
+                new RawValueDataSerializer<>(
+                        new KryoSerializer<>(WrappedString.class, new 
SerializerConfigImpl()));
+        return new RowDataSerializer(
+                new LogicalType[] {new RawType(RawValueData.class, 
rawValueSerializer)},
+                new TypeSerializer[] {rawValueSerializer});
+    }
+
+    /** Class used for concurrent testing with KryoSerializer. */
+    private static class WrappedString {
+
+        private final String content;
 
-        private static RowDataSerializer getRowSerializer() {
-            RawValueDataSerializer<WrappedString> rawValueSerializer =
-                    new RawValueDataSerializer<>(
-                            new KryoSerializer<>(WrappedString.class, new 
SerializerConfigImpl()));
-            return new RowDataSerializer(
-                    new LogicalType[] {new RawType(RawValueData.class, 
rawValueSerializer)},
-                    new TypeSerializer[] {rawValueSerializer});
+        WrappedString(String content) {
+            this.content = content;
         }
     }
+}
 
-    static final class RowDataSerializerWithNestedRowTest extends 
RowDataSerializerTest {
+final class RowDataSerializerWithNestedRowTest extends RowDataSerializerTest {
 
-        private static final DataType NESTED_DATA_TYPE =
-                DataTypes.ROW(
-                        DataTypes.FIELD("ri", DataTypes.INT()),
-                        DataTypes.FIELD("rs", DataTypes.STRING()),
-                        DataTypes.FIELD("rb", DataTypes.BIGINT()));
+    private static final DataType NESTED_DATA_TYPE =
+            DataTypes.ROW(
+                    DataTypes.FIELD("ri", DataTypes.INT()),
+                    DataTypes.FIELD("rs", DataTypes.STRING()),
+                    DataTypes.FIELD("rb", DataTypes.BIGINT()));
 
-        public RowDataSerializerWithNestedRowTest() {
-            super(getRowSerializer(), getData());
-        }
+    RowDataSerializerWithNestedRowTest() {
+        super(getRowSerializer(), getData());
+    }
 
-        private static RowData[] getData() {
-            final DataType outerDataType =
-                    DataTypes.ROW(
-                            DataTypes.FIELD("i", DataTypes.INT()),
-                            DataTypes.FIELD("r", NESTED_DATA_TYPE),
-                            DataTypes.FIELD("s", DataTypes.STRING()));
-
-            final RowDataSerializer outerSerializer =
-                    (RowDataSerializer)
-                            
InternalSerializers.<RowData>create(outerDataType.getLogicalType());
-
-            final GenericRowData outerRow1 =
-                    GenericRowData.of(
-                            12,
-                            GenericRowData.of(34, StringData.fromString("56"), 
78L),
-                            StringData.fromString("910"));
-            final RowData nestedRow1 = 
outerSerializer.toBinaryRow(outerRow1).getRow(1, 3);
-
-            final GenericRowData outerRow2 =
-                    GenericRowData.of(
-                            12, GenericRowData.of(null, 
StringData.fromString("56"), 78L), null);
-            final RowData nestedRow2 = 
outerSerializer.toBinaryRow(outerRow2).getRow(1, 3);
-
-            return new RowData[] {nestedRow1, nestedRow2};
-        }
+    private static RowData[] getData() {
+        final DataType outerDataType =
+                DataTypes.ROW(
+                        DataTypes.FIELD("i", DataTypes.INT()),
+                        DataTypes.FIELD("r", NESTED_DATA_TYPE),
+                        DataTypes.FIELD("s", DataTypes.STRING()));
+
+        final RowDataSerializer outerSerializer =
+                (RowDataSerializer)
+                        
InternalSerializers.<RowData>create(outerDataType.getLogicalType());
+
+        final GenericRowData outerRow1 =
+                GenericRowData.of(
+                        12,
+                        GenericRowData.of(34, StringData.fromString("56"), 
78L),
+                        StringData.fromString("910"));
+        final RowData nestedRow1 = 
outerSerializer.toBinaryRow(outerRow1).getRow(1, 3);
+
+        final GenericRowData outerRow2 =
+                GenericRowData.of(
+                        12, GenericRowData.of(null, 
StringData.fromString("56"), 78L), null);
+        final RowData nestedRow2 = 
outerSerializer.toBinaryRow(outerRow2).getRow(1, 3);
+
+        return new RowData[] {nestedRow1, nestedRow2};
+    }
 
-        private static RowDataSerializer getRowSerializer() {
-            return (RowDataSerializer)
-                    
InternalSerializers.<RowData>create(NESTED_DATA_TYPE.getLogicalType());
-        }
+    private static RowDataSerializer getRowSerializer() {
+        return (RowDataSerializer)
+                
InternalSerializers.<RowData>create(NESTED_DATA_TYPE.getLogicalType());
     }
+}
 
-    /**
-     * Converters and serializers always support nullability. The NOT NULL 
constraint is only
-     * considered on SQL semantic level but not data transfer. E.g. partial 
deletes (i.e. key-only
-     * upserts) set all non-key fields to null, regardless of logical type.
-     */
-    static final class RowDataSerializerWithNullForNotNullTypeTest extends 
RowDataSerializerTest {
-        public RowDataSerializerWithNullForNotNullTypeTest() {
-            super(getRowSerializer(), getData());
-        }
+/**
+ * Converters and serializers always support nullability. The NOT NULL 
constraint is only considered
+ * on SQL semantic level but not data transfer. E.g. partial deletes (i.e. 
key-only upserts) set all
+ * non-key fields to null, regardless of logical type.
+ */
+final class RowDataSerializerWithNullForNotNullTypeTest extends 
RowDataSerializerTest {
+    RowDataSerializerWithNullForNotNullTypeTest() {
+        super(getRowSerializer(), getData());
+    }
 
-        private static RowData[] getData() {
-            GenericRowData row = new GenericRowData(13);
-            row.setField(0, 2);
-            row.setField(1, null);
-            row.setField(3, null);
-            row.setField(4, null);
-            row.setField(5, null);
-            row.setField(6, null);
-            row.setField(7, null);
-            row.setField(8, null);
-            row.setField(9, null);
-            row.setField(10, null);
-            row.setField(11, null);
-            row.setField(12, null);
-
-            return new RowData[] {row};
-        }
+    private static RowData[] getData() {
+        GenericRowData row = new GenericRowData(13);
+        row.setField(0, 2);
+        row.setField(1, null);
+        row.setField(3, null);
+        row.setField(4, null);
+        row.setField(5, null);
+        row.setField(6, null);
+        row.setField(7, null);
+        row.setField(8, null);
+        row.setField(9, null);
+        row.setField(10, null);
+        row.setField(11, null);
+        row.setField(12, null);
+
+        return new RowData[] {row};
+    }
 
-        private static RowDataSerializer getRowSerializer() {
-            InternalTypeInfo<RowData> typeInfo =
-                    InternalTypeInfo.ofFields(
-                            new IntType(false),
-                            new SmallIntType(false),
-                            new BigIntType(false),
-                            new VarCharType(false, VarCharType.MAX_LENGTH),
-                            new CharType(false, CharType.MAX_LENGTH),
-                            new BinaryType(false, BinaryType.MAX_LENGTH),
-                            new VarBinaryType(false, VarBinaryType.MAX_LENGTH),
-                            new DateType(false),
-                            new DayTimeIntervalType(
-                                    false, 
DayTimeIntervalType.DayTimeResolution.DAY, 1, 6),
-                            new DecimalType(false, 10, 2),
-                            new FloatType(false),
-                            new DoubleType(false),
-                            new LocalZonedTimestampType(false, 3));
-
-            return typeInfo.toRowSerializer();
-        }
+    private static RowDataSerializer getRowSerializer() {
+        InternalTypeInfo<RowData> typeInfo =
+                InternalTypeInfo.ofFields(
+                        new IntType(false),
+                        new SmallIntType(false),
+                        new BigIntType(false),
+                        new VarCharType(false, VarCharType.MAX_LENGTH),
+                        new CharType(false, CharType.MAX_LENGTH),
+                        new BinaryType(false, BinaryType.MAX_LENGTH),
+                        new VarBinaryType(false, VarBinaryType.MAX_LENGTH),
+                        new DateType(false),
+                        new DayTimeIntervalType(
+                                false, 
DayTimeIntervalType.DayTimeResolution.DAY, 1, 6),
+                        new DecimalType(false, 10, 2),
+                        new FloatType(false),
+                        new DoubleType(false),
+                        new LocalZonedTimestampType(false, 3));
+
+        return typeInfo.toRowSerializer();
     }
 }
diff --git 
a/flink-table/flink-table-type-utils/src/test/java/org/apache/flink/table/runtime/typeutils/TimestampDataSerializerTest.java
 
b/flink-table/flink-table-type-utils/src/test/java/org/apache/flink/table/runtime/typeutils/TimestampDataSerializerTest.java
index c9883aed814..e3a7b64f235 100644
--- 
a/flink-table/flink-table-type-utils/src/test/java/org/apache/flink/table/runtime/typeutils/TimestampDataSerializerTest.java
+++ 
b/flink-table/flink-table-type-utils/src/test/java/org/apache/flink/table/runtime/typeutils/TimestampDataSerializerTest.java
@@ -22,61 +22,71 @@ import 
org.apache.flink.api.common.typeutils.SerializerTestBase;
 import org.apache.flink.api.common.typeutils.TypeSerializer;
 import org.apache.flink.table.data.TimestampData;
 
-/** Test for {@link TimestampDataSerializer}. */
-abstract class TimestampDataSerializerTest extends 
SerializerTestBase<TimestampData> {
-
-    @Override
-    protected TypeSerializer<TimestampData> createSerializer() {
-        return new TimestampDataSerializer(getPrecision());
-    }
-
-    @Override
-    protected int getLength() {
-        return (getPrecision() <= 3) ? 8 : 12;
-    }
-
-    @Override
-    protected Class<TimestampData> getTypeClass() {
-        return TimestampData.class;
-    }
+import org.junit.jupiter.api.Nested;
 
-    @Override
-    protected TimestampData[] getTestData() {
-        return new TimestampData[] {
-            TimestampData.fromEpochMillis(1),
-            TimestampData.fromEpochMillis(2),
-            TimestampData.fromEpochMillis(3),
-            TimestampData.fromEpochMillis(4)
-        };
-    }
-
-    protected abstract int getPrecision();
+/** Test for {@link TimestampDataSerializer}. */
+class TimestampDataSerializerTest {
 
-    static final class TimestampSerializer0Test extends 
TimestampDataSerializerTest {
+    @Nested
+    final class TimestampSerializer0Test extends 
TimestampDataSerializerTestBase {
         @Override
         protected int getPrecision() {
             return 0;
         }
     }
 
-    static final class TimestampSerializer3Test extends 
TimestampDataSerializerTest {
+    @Nested
+    final class TimestampSerializer3Test extends 
TimestampDataSerializerTestBase {
         @Override
         protected int getPrecision() {
             return 3;
         }
     }
 
-    static final class TimestampSerializer6Test extends 
TimestampDataSerializerTest {
+    @Nested
+    final class TimestampSerializer6Test extends 
TimestampDataSerializerTestBase {
         @Override
         protected int getPrecision() {
             return 6;
         }
     }
 
-    static final class TimestampSerializer8Test extends 
TimestampDataSerializerTest {
+    @Nested
+    final class TimestampSerializer8Test extends 
TimestampDataSerializerTestBase {
         @Override
         protected int getPrecision() {
             return 8;
         }
     }
+
+    abstract static class TimestampDataSerializerTestBase
+            extends SerializerTestBase<TimestampData> {
+
+        @Override
+        protected TypeSerializer<TimestampData> createSerializer() {
+            return new TimestampDataSerializer(getPrecision());
+        }
+
+        @Override
+        protected int getLength() {
+            return (getPrecision() <= 3) ? 8 : 12;
+        }
+
+        @Override
+        protected Class<TimestampData> getTypeClass() {
+            return TimestampData.class;
+        }
+
+        @Override
+        protected TimestampData[] getTestData() {
+            return new TimestampData[] {
+                TimestampData.fromEpochMillis(1),
+                TimestampData.fromEpochMillis(2),
+                TimestampData.fromEpochMillis(3),
+                TimestampData.fromEpochMillis(4)
+            };
+        }
+
+        protected abstract int getPrecision();
+    }
 }
diff --git 
a/flink-tests/src/test/java/org/apache/flink/test/completeness/TypeSerializerTestCoverageTest.java
 
b/flink-tests/src/test/java/org/apache/flink/test/completeness/TypeSerializerTestCoverageTest.java
index 0ac02614513..b46b69ddcc6 100644
--- 
a/flink-tests/src/test/java/org/apache/flink/test/completeness/TypeSerializerTestCoverageTest.java
+++ 
b/flink-tests/src/test/java/org/apache/flink/test/completeness/TypeSerializerTestCoverageTest.java
@@ -43,6 +43,7 @@ import 
org.apache.flink.api.common.typeutils.base.array.ShortPrimitiveArraySeria
 import org.apache.flink.api.common.typeutils.base.array.StringArraySerializer;
 import org.apache.flink.api.java.typeutils.runtime.CopyableValueSerializer;
 import org.apache.flink.api.java.typeutils.runtime.EitherSerializer;
+import org.apache.flink.api.java.typeutils.runtime.NullableSerializer;
 import org.apache.flink.api.java.typeutils.runtime.RowSerializer;
 import org.apache.flink.api.java.typeutils.runtime.Tuple0Serializer;
 import org.apache.flink.api.java.typeutils.runtime.TupleSerializer;
@@ -140,6 +141,7 @@ class TypeSerializerTestCoverageTest {
                         
SingleThreadAccessCheckingTypeSerializer.class.getName(),
                         GenericArraySerializer.class.getName(),
                         NullValueSerializer.class.getName(),
+                        NullableSerializer.class.getName(),
                         Tuple0Serializer.class.getName(),
                         CopyableValueSerializer.class.getName(),
                         VoidSerializer.class.getName(),

Reply via email to