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));
+ }
}