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 fb00668ce7a Add more test cases on MySQLDatabasePrivilegeCheckerTest
(#38126)
fb00668ce7a is described below
commit fb00668ce7a18c939ec8df071be5f7baae8dd3d0
Author: Liang Zhang <[email protected]>
AuthorDate: Sat Feb 21 22:52:45 2026 +0800
Add more test cases on MySQLDatabasePrivilegeCheckerTest (#38126)
---
.../checker/MySQLDatabasePrivilegeCheckerTest.java | 218 ++++++++++++---------
1 file changed, 130 insertions(+), 88 deletions(-)
diff --git
a/database/connector/dialect/mysql/src/test/java/org/apache/shardingsphere/database/connector/mysql/checker/MySQLDatabasePrivilegeCheckerTest.java
b/database/connector/dialect/mysql/src/test/java/org/apache/shardingsphere/database/connector/mysql/checker/MySQLDatabasePrivilegeCheckerTest.java
index f0c9eaceb28..13c62e261d0 100644
---
a/database/connector/dialect/mysql/src/test/java/org/apache/shardingsphere/database/connector/mysql/checker/MySQLDatabasePrivilegeCheckerTest.java
+++
b/database/connector/dialect/mysql/src/test/java/org/apache/shardingsphere/database/connector/mysql/checker/MySQLDatabasePrivilegeCheckerTest.java
@@ -17,23 +17,31 @@
package org.apache.shardingsphere.database.connector.mysql.checker;
+import
org.apache.shardingsphere.database.connector.core.checker.DialectDatabasePrivilegeChecker;
import
org.apache.shardingsphere.database.connector.core.checker.PrivilegeCheckType;
import
org.apache.shardingsphere.database.connector.core.exception.CheckDatabaseEnvironmentFailedException;
import
org.apache.shardingsphere.database.connector.core.exception.MissingRequiredPrivilegeException;
-import org.junit.jupiter.api.BeforeEach;
+import
org.apache.shardingsphere.database.connector.core.spi.DatabaseTypedSPILoader;
+import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.Answers;
+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 org.mockito.junit.jupiter.MockitoExtension;
import javax.sql.DataSource;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
+import java.util.stream.Stream;
import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -41,136 +49,170 @@ import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
class MySQLDatabasePrivilegeCheckerTest {
+ private final DatabaseType databaseType =
TypedSPILoader.getService(DatabaseType.class, "MySQL");
+
+ private final DialectDatabasePrivilegeChecker checker =
DatabaseTypedSPILoader.getService(DialectDatabasePrivilegeChecker.class,
databaseType);
+
@Mock
- private PreparedStatement preparedStatement;
+ private DataSource dataSource;
@Mock
- private ResultSet resultSet;
+ private Connection connection;
- @Mock(answer = Answers.RETURNS_DEEP_STUBS)
- private DataSource dataSource;
+ @Mock
+ private DatabaseMetaData databaseMetaData;
- @BeforeEach
- void setUp() throws SQLException {
-
when(dataSource.getConnection().prepareStatement(anyString())).thenReturn(preparedStatement);
- }
+ @Mock
+ private PreparedStatement preparedStatement;
- @Test
- void assertCheckPipelinePrivilegeWithParticularSuccess() throws
SQLException {
- when(preparedStatement.executeQuery()).thenReturn(resultSet);
- when(resultSet.next()).thenReturn(true);
- when(resultSet.getString(1)).thenReturn("GRANT REPLICATION SLAVE,
REPLICATION CLIENT ON *.* TO '%'@'%'");
- new MySQLDatabasePrivilegeChecker().check(dataSource,
PrivilegeCheckType.PIPELINE);
- verify(preparedStatement).executeQuery();
- }
+ @Mock
+ private ResultSet resultSet;
- @Test
- void assertCheckPipelinePrivilegeWithAllSuccess() throws SQLException {
- when(preparedStatement.executeQuery()).thenReturn(resultSet);
+ @ParameterizedTest(name = "{0}")
+ @MethodSource("checkSuccessArguments")
+ void assertCheckSuccess(final String name, final PrivilegeCheckType
privilegeCheckType, final int majorVersion, final String catalog, final String
grantedPrivilege) throws SQLException {
+ mockShowGrantsQuery();
+ if (PrivilegeCheckType.XA == privilegeCheckType) {
+ mockXAMetaData(majorVersion);
+ }
+ if (PrivilegeCheckType.SELECT == privilegeCheckType) {
+ when(connection.getCatalog()).thenReturn(catalog);
+ }
when(resultSet.next()).thenReturn(true);
- when(resultSet.getString(1)).thenReturn("GRANT ALL PRIVILEGES ON *.*
TO '%'@'%'");
- new MySQLDatabasePrivilegeChecker().check(dataSource,
PrivilegeCheckType.PIPELINE);
+ when(resultSet.getString(1)).thenReturn(grantedPrivilege);
+ checker.check(dataSource, privilegeCheckType);
verify(preparedStatement).executeQuery();
}
- @Test
- void assertCheckPipelinePrivilegeWithLackPrivileges() throws SQLException {
- when(preparedStatement.executeQuery()).thenReturn(resultSet);
- assertThrows(MissingRequiredPrivilegeException.class, () -> new
MySQLDatabasePrivilegeChecker().check(dataSource, PrivilegeCheckType.PIPELINE));
+ @ParameterizedTest(name = "{0}")
+ @MethodSource("checkMissingPrivilegeArguments")
+ void assertCheckWithMissingPrivilege(final String name,
+ final PrivilegeCheckType
privilegeCheckType, final int majorVersion, final String catalog, final boolean
containsGrantRow) throws SQLException {
+ mockShowGrantsQuery();
+ if (PrivilegeCheckType.XA == privilegeCheckType) {
+ mockXAMetaData(majorVersion);
+ }
+ if (PrivilegeCheckType.SELECT == privilegeCheckType) {
+ when(connection.getCatalog()).thenReturn(catalog);
+ }
+ if (containsGrantRow) {
+ when(resultSet.next()).thenReturn(true, false);
+ when(resultSet.getString(1)).thenReturn("GRANT INSERT ON *.* TO
'%'@'%'");
+ }
+ assertThrows(MissingRequiredPrivilegeException.class, () ->
checker.check(dataSource, privilegeCheckType));
}
@Test
- void assertCheckPipelinePrivilegeFailure() throws SQLException {
- when(preparedStatement.executeQuery()).thenReturn(resultSet);
- when(resultSet.next()).thenThrow(new SQLException(""));
- assertThrows(CheckDatabaseEnvironmentFailedException.class, () -> new
MySQLDatabasePrivilegeChecker().check(dataSource, PrivilegeCheckType.PIPELINE));
+ void assertCheckFailureWhenConnectionAcquisitionFails() throws
SQLException {
+ when(dataSource.getConnection()).thenThrow(SQLException.class);
+ assertThrows(CheckDatabaseEnvironmentFailedException.class, () ->
checker.check(dataSource, PrivilegeCheckType.PIPELINE));
}
@Test
- void assertCheckXAPrivilegeWithParticularSuccessInMySQL8() throws
SQLException {
- when(preparedStatement.executeQuery()).thenReturn(resultSet);
-
when(dataSource.getConnection().getMetaData().getDatabaseMajorVersion()).thenReturn(8);
- when(resultSet.next()).thenReturn(true);
- when(resultSet.getString(1)).thenReturn("GRANT XA_RECOVER_ADMIN ON *.*
TO '%'@'%'");
- new MySQLDatabasePrivilegeChecker().check(dataSource,
PrivilegeCheckType.XA);
- verify(preparedStatement).executeQuery();
+ void assertCheckFailureWhenExecuteQueryFails() throws SQLException {
+ mockConnectionAndPreparedStatement();
+ when(preparedStatement.executeQuery()).thenThrow(SQLException.class);
+ assertThrows(CheckDatabaseEnvironmentFailedException.class, () ->
checker.check(dataSource, PrivilegeCheckType.PIPELINE));
}
@Test
- void assertUnCheckXAPrivilegeInMySQL5() throws SQLException {
-
when(dataSource.getConnection().getMetaData().getDatabaseMajorVersion()).thenReturn(5);
- new MySQLDatabasePrivilegeChecker().check(dataSource,
PrivilegeCheckType.XA);
- verify(preparedStatement, never()).executeQuery();
+ void assertCheckFailureWhenReadResultSetFails() throws SQLException {
+ mockShowGrantsQuery();
+ when(resultSet.next()).thenThrow(SQLException.class);
+ assertThrows(CheckDatabaseEnvironmentFailedException.class, () ->
checker.check(dataSource, PrivilegeCheckType.PIPELINE));
}
@Test
- void assertCheckXAPrivilegeWithAllSuccessInMySQL8() throws SQLException {
- when(preparedStatement.executeQuery()).thenReturn(resultSet);
-
when(dataSource.getConnection().getMetaData().getDatabaseMajorVersion()).thenReturn(8);
- when(resultSet.next()).thenReturn(true);
- when(resultSet.getString(1)).thenReturn("GRANT ALL PRIVILEGES ON *.*
TO '%'@'%'");
- new MySQLDatabasePrivilegeChecker().check(dataSource,
PrivilegeCheckType.XA);
- verify(preparedStatement).executeQuery();
+ void assertCheckFailureWhenReadMySQLMajorVersionFails() throws
SQLException {
+ when(dataSource.getConnection()).thenReturn(connection);
+ when(connection.getMetaData()).thenReturn(databaseMetaData);
+
when(databaseMetaData.getDatabaseMajorVersion()).thenThrow(SQLException.class);
+ assertThrows(CheckDatabaseEnvironmentFailedException.class, () ->
checker.check(dataSource, PrivilegeCheckType.XA));
}
@Test
- void assertCheckXAPrivilegeLackPrivilegesInMySQL8() throws SQLException {
- when(preparedStatement.executeQuery()).thenReturn(resultSet);
-
when(dataSource.getConnection().getMetaData().getDatabaseMajorVersion()).thenReturn(8);
- assertThrows(MissingRequiredPrivilegeException.class, () -> new
MySQLDatabasePrivilegeChecker().check(dataSource, PrivilegeCheckType.XA));
+ void assertCheckFailureWhenCloseResultSetFails() throws SQLException {
+ mockShowGrantsQuery();
+ when(resultSet.next()).thenReturn(false);
+ doThrow(SQLException.class).when(resultSet).close();
+ assertThrows(CheckDatabaseEnvironmentFailedException.class, () ->
checker.check(dataSource, PrivilegeCheckType.PIPELINE));
}
@Test
- void assertCheckXAPrivilegeFailureInMySQL8() throws SQLException {
- when(preparedStatement.executeQuery()).thenReturn(resultSet);
-
when(dataSource.getConnection().getMetaData().getDatabaseMajorVersion()).thenReturn(8);
- when(resultSet.next()).thenThrow(new SQLException(""));
- assertThrows(CheckDatabaseEnvironmentFailedException.class, () -> new
MySQLDatabasePrivilegeChecker().check(dataSource, PrivilegeCheckType.XA));
+ void assertCheckFailureWhenClosePreparedStatementFails() throws
SQLException {
+ mockShowGrantsQuery();
+ when(resultSet.next()).thenReturn(false);
+ doThrow(SQLException.class).when(preparedStatement).close();
+ assertThrows(CheckDatabaseEnvironmentFailedException.class, () ->
checker.check(dataSource, PrivilegeCheckType.PIPELINE));
}
@Test
- void assertCheckSelectWithSelectPrivileges() throws SQLException {
- when(dataSource.getConnection().getCatalog()).thenReturn("foo_db");
- when(preparedStatement.executeQuery()).thenReturn(resultSet);
- when(resultSet.next()).thenReturn(true);
- when(resultSet.getString(1)).thenReturn("GRANT SELECT ON *.* TO
'%'@'%'");
- new MySQLDatabasePrivilegeChecker().check(dataSource,
PrivilegeCheckType.SELECT);
- verify(preparedStatement).executeQuery();
+ void assertCheckFailureWhenReadResultSetAndCloseResultSetFail() throws
SQLException {
+ mockShowGrantsQuery();
+ when(resultSet.next()).thenThrow(new SQLException("mocked result set
failure"));
+ doThrow(SQLException.class).when(resultSet).close();
+ assertThrows(CheckDatabaseEnvironmentFailedException.class, () ->
checker.check(dataSource, PrivilegeCheckType.PIPELINE));
}
@Test
- void assertCheckSelectWithSelectOnDatabasePrivileges() throws SQLException
{
- when(dataSource.getConnection().getCatalog()).thenReturn("foo_db");
- when(preparedStatement.executeQuery()).thenReturn(resultSet);
- when(resultSet.next()).thenReturn(true);
- when(resultSet.getString(1)).thenReturn("GRANT SELECT ON `FOO_DB`.* TO
'%'@'%'");
- new MySQLDatabasePrivilegeChecker().check(dataSource,
PrivilegeCheckType.SELECT);
- verify(preparedStatement).executeQuery();
+ void assertCheckFailureWhenReadResultSetAndClosePreparedStatementFail()
throws SQLException {
+ mockShowGrantsQuery();
+ when(resultSet.next()).thenThrow(SQLException.class);
+ doThrow(SQLException.class).when(preparedStatement).close();
+ assertThrows(CheckDatabaseEnvironmentFailedException.class, () ->
checker.check(dataSource, PrivilegeCheckType.PIPELINE));
}
@Test
- void assertCheckSelectWithAllPrivileges() throws SQLException {
- when(dataSource.getConnection().getCatalog()).thenReturn("foo_db");
- when(preparedStatement.executeQuery()).thenReturn(resultSet);
+ void assertCheckFailureWhenCloseConnectionFails() throws SQLException {
+ mockShowGrantsQuery();
when(resultSet.next()).thenReturn(true);
when(resultSet.getString(1)).thenReturn("GRANT ALL PRIVILEGES ON *.*
TO '%'@'%'");
- new MySQLDatabasePrivilegeChecker().check(dataSource,
PrivilegeCheckType.SELECT);
- verify(preparedStatement).executeQuery();
+ doThrow(SQLException.class).when(connection).close();
+ assertThrows(CheckDatabaseEnvironmentFailedException.class, () ->
checker.check(dataSource, PrivilegeCheckType.PIPELINE));
}
@Test
- void assertCheckSelectWithAllPrivilegesOnDatabase() throws SQLException {
- when(dataSource.getConnection().getCatalog()).thenReturn("foo_db");
- when(preparedStatement.executeQuery()).thenReturn(resultSet);
- when(resultSet.next()).thenReturn(true);
- when(resultSet.getString(1)).thenReturn("GRANT ALL PRIVILEGES ON
`FOO_DB`.* TO '%'@'%'");
- new MySQLDatabasePrivilegeChecker().check(dataSource,
PrivilegeCheckType.SELECT);
- verify(preparedStatement).executeQuery();
+ void assertCheckSkipsXAInMySQL5() throws SQLException {
+ when(dataSource.getConnection()).thenReturn(connection);
+ when(connection.getMetaData()).thenReturn(databaseMetaData);
+ when(databaseMetaData.getDatabaseMajorVersion()).thenReturn(5);
+ checker.check(dataSource, PrivilegeCheckType.XA);
+ verify(preparedStatement, never()).executeQuery();
}
- @Test
- void assertCheckSelectWithLackPrivileges() throws SQLException {
+ private void mockShowGrantsQuery() throws SQLException {
+ mockConnectionAndPreparedStatement();
when(preparedStatement.executeQuery()).thenReturn(resultSet);
- assertThrows(MissingRequiredPrivilegeException.class, () -> new
MySQLDatabasePrivilegeChecker().check(dataSource, PrivilegeCheckType.SELECT));
+ }
+
+ private void mockConnectionAndPreparedStatement() throws SQLException {
+ when(dataSource.getConnection()).thenReturn(connection);
+ when(connection.prepareStatement("SHOW
GRANTS")).thenReturn(preparedStatement);
+ }
+
+ private void mockXAMetaData(final int majorVersion) throws SQLException {
+ when(connection.getMetaData()).thenReturn(databaseMetaData);
+
when(databaseMetaData.getDatabaseMajorVersion()).thenReturn(majorVersion);
+ }
+
+ private static Stream<Arguments> checkSuccessArguments() {
+ return Stream.of(
+ Arguments.of("pipeline with replication privilege",
PrivilegeCheckType.PIPELINE, 0, null, "GRANT REPLICATION SLAVE, REPLICATION
CLIENT ON *.* TO '%'@'%'"),
+ Arguments.of("pipeline with all privileges",
PrivilegeCheckType.PIPELINE, 0, null, "GRANT ALL PRIVILEGES ON *.* TO '%'@'%'"),
+ Arguments.of("xa with xa recover admin on mysql8",
PrivilegeCheckType.XA, 8, null, "GRANT XA_RECOVER_ADMIN ON *.* TO '%'@'%'"),
+ Arguments.of("xa with all privileges on mysql8",
PrivilegeCheckType.XA, 8, null, "GRANT ALL PRIVILEGES ON *.* TO '%'@'%'"),
+ Arguments.of("select with select privilege on all databases",
PrivilegeCheckType.SELECT, 0, "foo_db", "GRANT SELECT ON *.* TO '%'@'%'"),
+ Arguments.of("select with select privilege on target
database", PrivilegeCheckType.SELECT, 0, "foo_db", "GRANT SELECT ON `FOO_DB`.*
TO '%'@'%'"),
+ Arguments.of("select with all privileges on all databases",
PrivilegeCheckType.SELECT, 0, "foo_db", "GRANT ALL PRIVILEGES ON *.* TO
'%'@'%'"),
+ Arguments.of("select with all privileges on target database",
PrivilegeCheckType.SELECT, 0, "foo_db", "GRANT ALL PRIVILEGES ON `FOO_DB`.* TO
'%'@'%'"));
+ }
+
+ private static Stream<Arguments> checkMissingPrivilegeArguments() {
+ return Stream.of(
+ Arguments.of("pipeline without grant rows",
PrivilegeCheckType.PIPELINE, 0, null, false),
+ Arguments.of("pipeline with unrelated grant row",
PrivilegeCheckType.PIPELINE, 0, null, true),
+ Arguments.of("xa without grant rows on mysql8",
PrivilegeCheckType.XA, 8, null, false),
+ Arguments.of("select with unrelated grant row",
PrivilegeCheckType.SELECT, 0, "foo_db", true),
+ Arguments.of("none with unrelated grant row",
PrivilegeCheckType.NONE, 0, null, true));
}
}