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

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


The following commit(s) were added to refs/heads/master by this push:
     new cba92290105 Add more test cases on ResultSetMapperTest (#38110)
cba92290105 is described below

commit cba9229010520c40e1f5e64eb1225074e7d36141
Author: Liang Zhang <[email protected]>
AuthorDate: Fri Feb 20 13:03:23 2026 +0800

    Add more test cases on ResultSetMapperTest (#38110)
    
    * Add more test cases on ResultSetMapperTest
    
    * Add more test cases on ResultSetMapperTest
    
    * Add more test cases on ResultSetMapperTest
---
 .codex/skills/gen-ut/SKILL.md                      |  50 +++++-
 .../core/resultset/ResultSetMapperTest.java        | 197 ++++++++++-----------
 2 files changed, 138 insertions(+), 109 deletions(-)

diff --git a/.codex/skills/gen-ut/SKILL.md b/.codex/skills/gen-ut/SKILL.md
index f4ebb0e68ef..0631dc73a86 100644
--- a/.codex/skills/gen-ut/SKILL.md
+++ b/.codex/skills/gen-ut/SKILL.md
@@ -104,8 +104,10 @@ Module resolution order:
     - A. target public method and branch skeleton are consistent;
     - B. scenario differences mainly come from input data;
     - C. assertion skeleton is consistent, or only declared assertion 
differences exist;
-    - D. parameter sample count is at least 3.
+    - D. parameter sample count is at least 3;
+    - E. parameterized test body does not require dispatch logic via `switch`.
   - "Declared assertion differences" means differences explicitly recorded in 
the delivery report.
+  - If a candidate requires `switch` in a `@ParameterizedTest` body to 
distinguish argument rows, it is not high-fit and `MUST NOT` be refactored to 
parameterized form.
   - High-fit candidates `MUST` be refactored directly to parameterized form.
   - For high-fit candidates, a "do not recommend refactor" conclusion is 
allowed only when refactoring causes significant readability/diagnosability 
regression, and the exception `MUST` include a `Necessity reason tag` with 
concrete evidence.
   - Parameter construction `MUST` use `Arguments + @MethodSource`.
@@ -166,6 +168,7 @@ Module resolution order:
   - `R15-C` (scope mutation guard): test-generation tasks `MUST NOT` introduce 
new diffs under any `src/main/` path.
   - `R15-D` (parameterized argument floor): each `@ParameterizedTest` `MUST` 
bind to `@MethodSource` providers that together contain at least 3 `Arguments` 
rows; otherwise it is a violation.
   - `R15-E` (parameterized name parameter): each `@ParameterizedTest` method 
`MUST` declare the first parameter exactly as `final String name`.
+  - `R15-F` (parameterized switch ban): `@ParameterizedTest` method bodies 
`MUST NOT` contain `switch` statements.
 
 ## Workflow
 
@@ -483,6 +486,51 @@ PY
 '
 ```
 
+5.4 `R15-F` parameterized switch ban scan:
+```bash
+bash -lc '
+python3 - <ResolvedTestFileSet> <<'"'"'PY'"'"'
+import re
+import sys
+from pathlib import Path
+
+PARAM_METHOD_PATTERN = 
re.compile(r"@ParameterizedTest(?:\\s*\\([^)]*\\))?\\s*(?:@\\w+(?:\\s*\\([^)]*\\))?\\s*)*void\\s+(assert\\w+)\\s*\\([^)]*\\)\\s*\\{",
 re.S)
+SWITCH_PATTERN = re.compile(r"\\bswitch\\s*\\(")
+
+def extract_block(text, brace_index):
+    depth = 0
+    index = brace_index
+    while index < len(text):
+        if "{" == text[index]:
+            depth += 1
+        elif "}" == text[index]:
+            depth -= 1
+            if 0 == depth:
+                return text[brace_index + 1:index]
+        index += 1
+    return ""
+
+violations = []
+for path in (each for each in sys.argv[1:] if each.endswith(".java")):
+    source = Path(path).read_text(encoding="utf-8")
+    for match in PARAM_METHOD_PATTERN.finditer(source):
+        method_name = match.group(1)
+        line = source.count("\\n", 0, match.start()) + 1
+        brace_index = source.find("{", match.start())
+        if brace_index < 0:
+            continue
+        body = extract_block(source, brace_index)
+        if SWITCH_PATTERN.search(body):
+            violations.append(f"{path}:{line} method={method_name}")
+if violations:
+    print("[R15-F] @ParameterizedTest method body must not contain switch")
+    for each in violations:
+        print(each)
+    sys.exit(1)
+PY
+'
+```
+
 6. `R14` hard-gate scan:
 ```bash
 bash -lc '
diff --git 
a/database/connector/core/src/test/java/org/apache/shardingsphere/database/connector/core/resultset/ResultSetMapperTest.java
 
b/database/connector/core/src/test/java/org/apache/shardingsphere/database/connector/core/resultset/ResultSetMapperTest.java
index 04651482621..8f6e230a9fe 100644
--- 
a/database/connector/core/src/test/java/org/apache/shardingsphere/database/connector/core/resultset/ResultSetMapperTest.java
+++ 
b/database/connector/core/src/test/java/org/apache/shardingsphere/database/connector/core/resultset/ResultSetMapperTest.java
@@ -25,6 +25,9 @@ import 
org.apache.shardingsphere.test.infra.framework.extension.mock.StaticMockS
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
 import org.mockito.Mock;
 
 import java.math.BigDecimal;
@@ -40,9 +43,10 @@ import java.sql.Time;
 import java.sql.Timestamp;
 import java.sql.Types;
 import java.util.Optional;
+import java.util.stream.Stream;
 
-import static org.hamcrest.Matchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
 import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.Mockito.mock;
@@ -52,7 +56,7 @@ import static org.mockito.Mockito.when;
 @StaticMockSettings(DatabaseTypedSPILoader.class)
 class ResultSetMapperTest {
     
-    private DatabaseType databaseType;
+    private final DatabaseType databaseType = 
TypedSPILoader.getService(DatabaseType.class, "FIXTURE");
     
     @Mock
     private ResultSet resultSet;
@@ -62,7 +66,6 @@ class ResultSetMapperTest {
     
     @BeforeEach
     void setUp() throws SQLException {
-        databaseType = TypedSPILoader.getService(DatabaseType.class, 
"FIXTURE");
         when(resultSet.getMetaData()).thenReturn(metaData);
     }
     
@@ -74,38 +77,6 @@ class ResultSetMapperTest {
         assertTrue((Boolean) new ResultSetMapper(databaseType).load(resultSet, 
1));
     }
     
-    @Test
-    void assertLoadTinyIntValueWithDialectResultSetMapper() throws 
SQLException {
-        when(metaData.getColumnType(1)).thenReturn(Types.TINYINT);
-        DialectResultSetMapper dialectResultSetMapper = 
mock(DialectResultSetMapper.class);
-        when(DatabaseTypedSPILoader.findService(DialectResultSetMapper.class, 
databaseType)).thenReturn(Optional.of(dialectResultSetMapper));
-        when(dialectResultSetMapper.getSmallintValue(resultSet, 
1)).thenReturn(1);
-        assertThat(new ResultSetMapper(databaseType).load(resultSet, 1), 
is(1));
-    }
-    
-    @Test
-    void assertLoadTinyIntValueWithoutDialectResultSetMapper() throws 
SQLException {
-        when(metaData.getColumnType(1)).thenReturn(Types.TINYINT);
-        when(resultSet.getInt(1)).thenReturn(1);
-        assertThat(new ResultSetMapper(databaseType).load(resultSet, 1), 
is(1));
-    }
-    
-    @Test
-    void assertLoadSmallIntValueWithDialectResultSetMapper() throws 
SQLException {
-        when(metaData.getColumnType(1)).thenReturn(Types.SMALLINT);
-        DialectResultSetMapper dialectResultSetMapper = 
mock(DialectResultSetMapper.class);
-        when(DatabaseTypedSPILoader.findService(DialectResultSetMapper.class, 
databaseType)).thenReturn(Optional.of(dialectResultSetMapper));
-        when(dialectResultSetMapper.getSmallintValue(resultSet, 
1)).thenReturn(1);
-        assertThat(new ResultSetMapper(databaseType).load(resultSet, 1), 
is(1));
-    }
-    
-    @Test
-    void assertLoadSmallIntValueWithoutDialectResultSetMapper() throws 
SQLException {
-        when(metaData.getColumnType(1)).thenReturn(Types.SMALLINT);
-        when(resultSet.getInt(1)).thenReturn(1);
-        assertThat(new ResultSetMapper(databaseType).load(resultSet, 1), 
is(1));
-    }
-    
     @Test
     void assertLoadSignedIntegerValue() throws SQLException {
         when(metaData.getColumnType(1)).thenReturn(Types.INTEGER);
@@ -143,55 +114,6 @@ class ResultSetMapperTest {
         assertNull(new ResultSetMapper(databaseType).load(resultSet, 1));
     }
     
-    @Test
-    void assertLoadNumericValue() throws SQLException {
-        when(metaData.getColumnType(1)).thenReturn(Types.NUMERIC);
-        when(resultSet.getBigDecimal(1)).thenReturn(new BigDecimal("1"));
-        assertThat(new ResultSetMapper(databaseType).load(resultSet, 1), 
is(new BigDecimal("1")));
-    }
-    
-    @Test
-    void assertLoadDecimalValue() throws SQLException {
-        when(metaData.getColumnType(1)).thenReturn(Types.DECIMAL);
-        when(resultSet.getBigDecimal(1)).thenReturn(new BigDecimal("1"));
-        assertThat(new ResultSetMapper(databaseType).load(resultSet, 1), 
is(new BigDecimal("1")));
-    }
-    
-    @Test
-    void assertLoadFloatValue() throws SQLException {
-        when(metaData.getColumnType(1)).thenReturn(Types.FLOAT);
-        when(resultSet.getDouble(1)).thenReturn(1D);
-        assertThat(new ResultSetMapper(databaseType).load(resultSet, 1), 
is(1D));
-    }
-    
-    @Test
-    void assertLoadDoubleValue() throws SQLException {
-        when(metaData.getColumnType(1)).thenReturn(Types.DOUBLE);
-        when(resultSet.getDouble(1)).thenReturn(1D);
-        assertThat(new ResultSetMapper(databaseType).load(resultSet, 1), 
is(1D));
-    }
-    
-    @Test
-    void assertLoadCharValue() throws SQLException {
-        when(metaData.getColumnType(1)).thenReturn(Types.CHAR);
-        when(resultSet.getString(1)).thenReturn("foo");
-        assertThat(new ResultSetMapper(databaseType).load(resultSet, 1), 
is("foo"));
-    }
-    
-    @Test
-    void assertLoadVarcharValue() throws SQLException {
-        when(metaData.getColumnType(1)).thenReturn(Types.VARCHAR);
-        when(resultSet.getString(1)).thenReturn("foo");
-        assertThat(new ResultSetMapper(databaseType).load(resultSet, 1), 
is("foo"));
-    }
-    
-    @Test
-    void assertLoadLongVarcharValue() throws SQLException {
-        when(metaData.getColumnType(1)).thenReturn(Types.LONGVARCHAR);
-        when(resultSet.getString(1)).thenReturn("foo");
-        assertThat(new ResultSetMapper(databaseType).load(resultSet, 1), 
is("foo"));
-    }
-    
     @Test
     void assertLoadDateValueWithoutDialectResultSetMapper() throws 
SQLException {
         when(metaData.getColumnType(1)).thenReturn(Types.DATE);
@@ -208,6 +130,16 @@ class ResultSetMapperTest {
         assertThat(new ResultSetMapper(databaseType).load(resultSet, 1), 
is(new Date(0L)));
     }
     
+    @Test
+    void assertLoadObjectValueWithDialectResultSetMapper() throws SQLException 
{
+        when(metaData.getColumnType(1)).thenReturn(Types.JAVA_OBJECT);
+        DialectResultSetMapper dialectResultSetMapper = 
mock(DialectResultSetMapper.class);
+        Object object = new Object();
+        when(DatabaseTypedSPILoader.findService(DialectResultSetMapper.class, 
databaseType)).thenReturn(Optional.of(dialectResultSetMapper));
+        when(dialectResultSetMapper.getDefaultValue(resultSet, 1, 
Types.JAVA_OBJECT)).thenReturn(object);
+        assertThat(new ResultSetMapper(databaseType).load(resultSet, 1), 
is(object));
+    }
+    
     @Test
     void assertLoadTimeValue() throws SQLException {
         when(metaData.getColumnType(1)).thenReturn(Types.TIME);
@@ -238,30 +170,6 @@ class ResultSetMapperTest {
         assertThat(new ResultSetMapper(databaseType).load(resultSet, 1), 
is(clob));
     }
     
-    @Test
-    void assertLoadBinaryValue() throws SQLException {
-        when(metaData.getColumnType(1)).thenReturn(Types.BINARY);
-        byte[] bytes = new byte[0];
-        when(resultSet.getBytes(1)).thenReturn(bytes);
-        assertThat(new ResultSetMapper(databaseType).load(resultSet, 1), 
is(bytes));
-    }
-    
-    @Test
-    void assertLoadVarbinaryValue() throws SQLException {
-        when(metaData.getColumnType(1)).thenReturn(Types.VARBINARY);
-        byte[] bytes = new byte[0];
-        when(resultSet.getBytes(1)).thenReturn(bytes);
-        assertThat(new ResultSetMapper(databaseType).load(resultSet, 1), 
is(bytes));
-    }
-    
-    @Test
-    void assertLoadLongVarbinaryValue() throws SQLException {
-        when(metaData.getColumnType(1)).thenReturn(Types.LONGVARBINARY);
-        byte[] bytes = new byte[0];
-        when(resultSet.getBytes(1)).thenReturn(bytes);
-        assertThat(new ResultSetMapper(databaseType).load(resultSet, 1), 
is(bytes));
-    }
-    
     @Test
     void assertLoadArrayValue() throws SQLException {
         when(metaData.getColumnType(1)).thenReturn(Types.ARRAY);
@@ -277,4 +185,77 @@ class ResultSetMapperTest {
         when(resultSet.getObject(1)).thenReturn(object);
         assertThat(new ResultSetMapper(databaseType).load(resultSet, 1), 
is(object));
     }
+    
+    @ParameterizedTest(name = "{0}")
+    @MethodSource("smallintTypeArguments")
+    void assertLoadSmallintValue(final String name, final int columnType, 
final boolean hasDialectResultSetMapper) throws SQLException {
+        when(metaData.getColumnType(1)).thenReturn(columnType);
+        if (hasDialectResultSetMapper) {
+            DialectResultSetMapper dialectResultSetMapper = 
mock(DialectResultSetMapper.class);
+            
when(DatabaseTypedSPILoader.findService(DialectResultSetMapper.class, 
databaseType)).thenReturn(Optional.of(dialectResultSetMapper));
+            when(dialectResultSetMapper.getSmallintValue(resultSet, 
1)).thenReturn(1);
+        } else {
+            when(resultSet.getInt(1)).thenReturn(1);
+        }
+        assertThat(new ResultSetMapper(databaseType).load(resultSet, 1), 
is(1));
+    }
+    
+    @ParameterizedTest(name = "{0}")
+    @MethodSource("numericAndFloatingTypeArguments")
+    void assertLoadNumericAndFloatingValue(final String name, final int 
columnType, final Object expected) throws SQLException {
+        when(metaData.getColumnType(1)).thenReturn(columnType);
+        if (Types.FLOAT == columnType || Types.DOUBLE == columnType) {
+            when(resultSet.getDouble(1)).thenReturn((Double) expected);
+        } else {
+            when(resultSet.getBigDecimal(1)).thenReturn((BigDecimal) expected);
+        }
+        assertThat(new ResultSetMapper(databaseType).load(resultSet, 1), 
is(expected));
+    }
+    
+    @ParameterizedTest(name = "{0}")
+    @MethodSource("stringTypeArguments")
+    void assertLoadStringValue(final String name, final int columnType) throws 
SQLException {
+        when(metaData.getColumnType(1)).thenReturn(columnType);
+        when(resultSet.getString(1)).thenReturn("foo");
+        assertThat(new ResultSetMapper(databaseType).load(resultSet, 1), 
is("foo"));
+    }
+    
+    @ParameterizedTest(name = "{0}")
+    @MethodSource("binaryTypeArguments")
+    void assertLoadBinaryValue(final String name, final int columnType) throws 
SQLException {
+        when(metaData.getColumnType(1)).thenReturn(columnType);
+        byte[] bytes = new byte[0];
+        when(resultSet.getBytes(1)).thenReturn(bytes);
+        assertThat(new ResultSetMapper(databaseType).load(resultSet, 1), 
is(bytes));
+    }
+    
+    private static Stream<Arguments> smallintTypeArguments() {
+        return Stream.of(
+                Arguments.of("tinyint with dialect result set mapper", 
Types.TINYINT, true),
+                Arguments.of("tinyint without dialect result set mapper", 
Types.TINYINT, false),
+                Arguments.of("smallint with dialect result set mapper", 
Types.SMALLINT, true),
+                Arguments.of("smallint without dialect result set mapper", 
Types.SMALLINT, false));
+    }
+    
+    private static Stream<Arguments> numericAndFloatingTypeArguments() {
+        return Stream.of(
+                Arguments.of("numeric", Types.NUMERIC, new BigDecimal("1")),
+                Arguments.of("decimal", Types.DECIMAL, new BigDecimal("1")),
+                Arguments.of("float", Types.FLOAT, 1D),
+                Arguments.of("double", Types.DOUBLE, 1D));
+    }
+    
+    private static Stream<Arguments> stringTypeArguments() {
+        return Stream.of(
+                Arguments.of("char", Types.CHAR),
+                Arguments.of("varchar", Types.VARCHAR),
+                Arguments.of("longvarchar", Types.LONGVARCHAR));
+    }
+    
+    private static Stream<Arguments> binaryTypeArguments() {
+        return Stream.of(
+                Arguments.of("binary", Types.BINARY),
+                Arguments.of("varbinary", Types.VARBINARY),
+                Arguments.of("longvarbinary", Types.LONGVARBINARY));
+    }
 }

Reply via email to