From 6ebe0f7e4c7d06aa362fd15744e7a305d2374647 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E7=BF=8A=20SionYang?= Date: Mon, 21 Oct 2024 16:59:27 +0800 Subject: [PATCH] Add Unit test for persistence module. (#12768) --- .../ExternalDataSourceServiceImpl.java | 2 +- .../persistence/exception/NJdbcException.java | 4 + .../EmbeddedPaginationHelperImpl.java | 136 +-- .../embedded/operate/DatabaseOperate.java | 23 - .../ExternalStoragePaginationHelperImpl.java | 149 +-- .../utils/ConnectionCheckUtil.java | 18 +- .../DatasourceConfigurationTest.java | 133 +++ .../datasource/DynamicDataSourceTest.java | 41 +- .../ExternalDataSourceServiceImplTest.java | 156 ++- .../LocalDataSourceServiceImplTest.java | 83 +- .../datasource/mock/MockConnection.java | 314 ++++++ .../datasource/mock/MockDriver.java | 63 ++ .../mock/MockPreparedStatement.java | 539 ++++++++++ .../datasource/mock/MockResultSet.java | 998 ++++++++++++++++++ .../datasource/mock/MockStatement.java | 246 +++++ .../exception/NJdbcExceptionTest.java | 79 ++ .../nacos/persistence/model/PageTest.java | 34 + .../persistence/model/event/EventTest.java | 48 + .../repository/RowMapperManagerTest.java | 89 ++ .../EmbeddedPaginationHelperImplTest.java | 350 ++++++ .../EmbeddedStorageContextHolderTest.java | 70 ++ .../hook/EmbeddedApplyHookHolderTest.java | 57 + .../operate/BaseDatabaseOperateTest.java | 205 ++++ .../embedded/operate/DatabaseOperateTest.java | 47 + .../StandaloneDatabaseOperateImplTest.java | 136 ++- .../embedded/sql/ModifyRequestTest.java | 35 + .../embedded/sql/SelectRequestTest.java | 41 + ...ternalStoragePaginationHelperImplTest.java | 343 ++++++ .../utils/PersistenceExecutorTest.java | 17 + .../test/resources/META-INF/derby-schema.sql | 227 ++++ .../resources/META-INF/test-derby-import.sql | 22 + 31 files changed, 4426 insertions(+), 279 deletions(-) create mode 100644 persistence/src/test/java/com/alibaba/nacos/persistence/configuration/DatasourceConfigurationTest.java create mode 100644 persistence/src/test/java/com/alibaba/nacos/persistence/datasource/mock/MockConnection.java create mode 100644 persistence/src/test/java/com/alibaba/nacos/persistence/datasource/mock/MockDriver.java create mode 100644 persistence/src/test/java/com/alibaba/nacos/persistence/datasource/mock/MockPreparedStatement.java create mode 100644 persistence/src/test/java/com/alibaba/nacos/persistence/datasource/mock/MockResultSet.java create mode 100644 persistence/src/test/java/com/alibaba/nacos/persistence/datasource/mock/MockStatement.java create mode 100644 persistence/src/test/java/com/alibaba/nacos/persistence/exception/NJdbcExceptionTest.java create mode 100644 persistence/src/test/java/com/alibaba/nacos/persistence/model/PageTest.java create mode 100644 persistence/src/test/java/com/alibaba/nacos/persistence/model/event/EventTest.java create mode 100644 persistence/src/test/java/com/alibaba/nacos/persistence/repository/RowMapperManagerTest.java create mode 100644 persistence/src/test/java/com/alibaba/nacos/persistence/repository/embedded/EmbeddedPaginationHelperImplTest.java create mode 100644 persistence/src/test/java/com/alibaba/nacos/persistence/repository/embedded/EmbeddedStorageContextHolderTest.java create mode 100644 persistence/src/test/java/com/alibaba/nacos/persistence/repository/embedded/hook/EmbeddedApplyHookHolderTest.java create mode 100644 persistence/src/test/java/com/alibaba/nacos/persistence/repository/embedded/operate/BaseDatabaseOperateTest.java create mode 100644 persistence/src/test/java/com/alibaba/nacos/persistence/repository/embedded/operate/DatabaseOperateTest.java create mode 100644 persistence/src/test/java/com/alibaba/nacos/persistence/repository/embedded/sql/ModifyRequestTest.java create mode 100644 persistence/src/test/java/com/alibaba/nacos/persistence/repository/embedded/sql/SelectRequestTest.java create mode 100644 persistence/src/test/java/com/alibaba/nacos/persistence/repository/extrnal/ExternalStoragePaginationHelperImplTest.java create mode 100644 persistence/src/test/resources/META-INF/derby-schema.sql create mode 100644 persistence/src/test/resources/META-INF/test-derby-import.sql diff --git a/persistence/src/main/java/com/alibaba/nacos/persistence/datasource/ExternalDataSourceServiceImpl.java b/persistence/src/main/java/com/alibaba/nacos/persistence/datasource/ExternalDataSourceServiceImpl.java index 739487b83cd..9e9ef72ab1d 100644 --- a/persistence/src/main/java/com/alibaba/nacos/persistence/datasource/ExternalDataSourceServiceImpl.java +++ b/persistence/src/main/java/com/alibaba/nacos/persistence/datasource/ExternalDataSourceServiceImpl.java @@ -185,7 +185,7 @@ public boolean checkMasterWritable() { return result == 0; } } catch (CannotGetJdbcConnectionException e) { - LOGGER.error("[db-error] " + e.toString(), e); + LOGGER.error("[db-error] " + e, e); return false; } diff --git a/persistence/src/main/java/com/alibaba/nacos/persistence/exception/NJdbcException.java b/persistence/src/main/java/com/alibaba/nacos/persistence/exception/NJdbcException.java index 2d9581da783..f352779e673 100644 --- a/persistence/src/main/java/com/alibaba/nacos/persistence/exception/NJdbcException.java +++ b/persistence/src/main/java/com/alibaba/nacos/persistence/exception/NJdbcException.java @@ -49,4 +49,8 @@ public NJdbcException(String msg, Throwable cause) { public NJdbcException(Throwable cause) { super("", cause); } + + public String getOriginExceptionName() { + return originExceptionName; + } } diff --git a/persistence/src/main/java/com/alibaba/nacos/persistence/repository/embedded/EmbeddedPaginationHelperImpl.java b/persistence/src/main/java/com/alibaba/nacos/persistence/repository/embedded/EmbeddedPaginationHelperImpl.java index 2b77bf37cca..0d702e0d98f 100644 --- a/persistence/src/main/java/com/alibaba/nacos/persistence/repository/embedded/EmbeddedPaginationHelperImpl.java +++ b/persistence/src/main/java/com/alibaba/nacos/persistence/repository/embedded/EmbeddedPaginationHelperImpl.java @@ -31,7 +31,7 @@ * @author boyan * @date 2010-5-6 */ -public class EmbeddedPaginationHelperImpl implements PaginationHelper { +public class EmbeddedPaginationHelperImpl implements PaginationHelper { private final DatabaseOperate databaseOperate; @@ -59,66 +59,27 @@ public Page fetchPage(final String sqlCountRows, final String sqlFetchRows, f @Override public Page fetchPage(final String sqlCountRows, final String sqlFetchRows, Object[] args, final int pageNo, final int pageSize, final Long lastMaxId, final RowMapper rowMapper) { - if (pageNo <= 0 || pageSize <= 0) { - throw new IllegalArgumentException("pageNo and pageSize must be greater than zero"); - } - - // Query the total number of current records - Integer rowCountInt = databaseOperate.queryOne(sqlCountRows, args, Integer.class); - if (rowCountInt == null) { - throw new IllegalArgumentException("fetchPageLimit error"); - } - - // Count pages - int pageCount = rowCountInt / pageSize; - if (rowCountInt > pageSize * pageCount) { - pageCount++; - } - - // Create Page object - final Page page = new Page<>(); - page.setPageNumber(pageNo); - page.setPagesAvailable(pageCount); - page.setTotalCount(rowCountInt); - - if (pageNo > pageCount) { - return page; - } - - List result = databaseOperate.queryMany(sqlFetchRows, args, rowMapper); - for (E item : result) { - page.getPageItems().add(item); - } - return page; + return doFetchPage(sqlCountRows, args, sqlFetchRows, args, pageNo, pageSize, rowMapper); } @Override public Page fetchPageLimit(final String sqlCountRows, final String sqlFetchRows, final Object[] args, final int pageNo, final int pageSize, final RowMapper rowMapper) { - if (pageNo <= 0 || pageSize <= 0) { - throw new IllegalArgumentException("pageNo and pageSize must be greater than zero"); - } - // Query the total number of current records - Integer rowCountInt = databaseOperate.queryOne(sqlCountRows, Integer.class); - if (rowCountInt == null) { - throw new IllegalArgumentException("fetchPageLimit error"); - } - - // Count pages - int pageCount = rowCountInt / pageSize; - if (rowCountInt > pageSize * pageCount) { - pageCount++; - } - + return doFetchPage(sqlCountRows, null, sqlFetchRows, args, pageNo, pageSize, rowMapper); + } + + @Override + public Page fetchPageLimit(final String sqlCountRows, final Object[] args1, final String sqlFetchRows, + final Object[] args2, final int pageNo, final int pageSize, final RowMapper rowMapper) { + return doFetchPage(sqlCountRows, args1, sqlFetchRows, args2, pageNo, pageSize, rowMapper); + } + + @Override + public Page fetchPageLimit(final String sqlFetchRows, final Object[] args, final int pageNo, final int pageSize, + final RowMapper rowMapper) { + checkPageInfo(pageNo, pageSize); // Create Page object final Page page = new Page<>(); - page.setPageNumber(pageNo); - page.setPagesAvailable(pageCount); - page.setTotalCount(rowCountInt); - - if (pageNo > pageCount) { - return page; - } List result = databaseOperate.queryMany(sqlFetchRows, args, rowMapper); for (E item : result) { @@ -128,13 +89,38 @@ public Page fetchPageLimit(final String sqlCountRows, final String sqlFetchRo } @Override - public Page fetchPageLimit(final String sqlCountRows, final Object[] args1, final String sqlFetchRows, - final Object[] args2, final int pageNo, final int pageSize, final RowMapper rowMapper) { + public Page fetchPageLimit(MapperResult countMapperResult, MapperResult mapperResult, int pageNo, int pageSize, + RowMapper rowMapper) { + return fetchPageLimit(countMapperResult.getSql(), countMapperResult.getParamList().toArray(), + mapperResult.getSql(), mapperResult.getParamList().toArray(), pageNo, pageSize, rowMapper); + } + + @Override + public void updateLimit(final String sql, final Object[] args) { + EmbeddedStorageContextHolder.addSqlContext(sql, args); + try { + databaseOperate.update(EmbeddedStorageContextHolder.getCurrentSqlContext()); + } finally { + EmbeddedStorageContextHolder.cleanAllContext(); + } + } + + private void checkPageInfo(final int pageNo, final int pageSize) { if (pageNo <= 0 || pageSize <= 0) { throw new IllegalArgumentException("pageNo and pageSize must be greater than zero"); } + } + + private Page doFetchPage(final String sqlCountRows, final Object[] countAgrs, final String sqlFetchRows, + final Object[] fetchArgs, final int pageNo, final int pageSize, final RowMapper rowMapper) { + checkPageInfo(pageNo, pageSize); // Query the total number of current records - Integer rowCountInt = databaseOperate.queryOne(sqlCountRows, args1, Integer.class); + Integer rowCountInt = null; + if (null != countAgrs) { + rowCountInt = databaseOperate.queryOne(sqlCountRows, countAgrs, Integer.class); + } else { + rowCountInt = databaseOperate.queryOne(sqlCountRows, Integer.class); + } if (rowCountInt == null) { throw new IllegalArgumentException("fetchPageLimit error"); } @@ -155,44 +141,10 @@ public Page fetchPageLimit(final String sqlCountRows, final Object[] args1, f return page; } - List result = databaseOperate.queryMany(sqlFetchRows, args2, rowMapper); - for (E item : result) { - page.getPageItems().add(item); - } - return page; - } - - @Override - public Page fetchPageLimit(final String sqlFetchRows, final Object[] args, final int pageNo, final int pageSize, - final RowMapper rowMapper) { - if (pageNo <= 0 || pageSize <= 0) { - throw new IllegalArgumentException("pageNo and pageSize must be greater than zero"); - } - // Create Page object - final Page page = new Page<>(); - - List result = databaseOperate.queryMany(sqlFetchRows, args, rowMapper); + List result = databaseOperate.queryMany(sqlFetchRows, fetchArgs, rowMapper); for (E item : result) { page.getPageItems().add(item); } return page; } - - @Override - public Page fetchPageLimit(MapperResult countMapperResult, MapperResult mapperResult, int pageNo, int pageSize, - RowMapper rowMapper) { - return fetchPageLimit(countMapperResult.getSql(), countMapperResult.getParamList().toArray(), - mapperResult.getSql(), mapperResult.getParamList().toArray(), pageNo, pageSize, rowMapper); - } - - @Override - public void updateLimit(final String sql, final Object[] args) { - EmbeddedStorageContextHolder.addSqlContext(sql, args); - try { - databaseOperate.update(EmbeddedStorageContextHolder.getCurrentSqlContext()); - } finally { - EmbeddedStorageContextHolder.cleanAllContext(); - } - } - } diff --git a/persistence/src/main/java/com/alibaba/nacos/persistence/repository/embedded/operate/DatabaseOperate.java b/persistence/src/main/java/com/alibaba/nacos/persistence/repository/embedded/operate/DatabaseOperate.java index 568d73f9eeb..9e154336518 100644 --- a/persistence/src/main/java/com/alibaba/nacos/persistence/repository/embedded/operate/DatabaseOperate.java +++ b/persistence/src/main/java/com/alibaba/nacos/persistence/repository/embedded/operate/DatabaseOperate.java @@ -24,7 +24,6 @@ import java.io.File; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.function.BiConsumer; @@ -152,26 +151,4 @@ default Boolean blockUpdate(BiConsumer consumer) { } } - /** - * data modify transaction The SqlContext to be executed in the current thread will be executed and automatically - * cleared. - * - * @return is success - */ - default CompletableFuture futureUpdate() { - try { - CompletableFuture future = new CompletableFuture<>(); - update(EmbeddedStorageContextHolder.getCurrentSqlContext(), (o, throwable) -> { - if (Objects.nonNull(throwable)) { - future.completeExceptionally(throwable); - return; - } - future.complete(o); - }); - return future; - } finally { - EmbeddedStorageContextHolder.cleanAllContext(); - } - } - } diff --git a/persistence/src/main/java/com/alibaba/nacos/persistence/repository/extrnal/ExternalStoragePaginationHelperImpl.java b/persistence/src/main/java/com/alibaba/nacos/persistence/repository/extrnal/ExternalStoragePaginationHelperImpl.java index 04d6e1e74d9..90fb7ec30e7 100644 --- a/persistence/src/main/java/com/alibaba/nacos/persistence/repository/extrnal/ExternalStoragePaginationHelperImpl.java +++ b/persistence/src/main/java/com/alibaba/nacos/persistence/repository/extrnal/ExternalStoragePaginationHelperImpl.java @@ -31,7 +31,7 @@ * @author liaochuntao */ -public class ExternalStoragePaginationHelperImpl implements PaginationHelper { +public class ExternalStoragePaginationHelperImpl implements PaginationHelper { private final JdbcTemplate jdbcTemplate; @@ -59,72 +59,13 @@ public Page fetchPage(final String sqlCountRows, final String sqlFetchRows, f @Override public Page fetchPage(final String sqlCountRows, final String sqlFetchRows, Object[] args, final int pageNo, final int pageSize, final Long lastMaxId, final RowMapper rowMapper) { - if (pageNo <= 0 || pageSize <= 0) { - throw new IllegalArgumentException("pageNo and pageSize must be greater than zero"); - } - - // Query the total number of current records. - Integer rowCountInt = jdbcTemplate.queryForObject(sqlCountRows, args, Integer.class); - if (rowCountInt == null) { - throw new IllegalArgumentException("fetchPageLimit error"); - } - - // Compute pages count - int pageCount = rowCountInt / pageSize; - if (rowCountInt > pageSize * pageCount) { - pageCount++; - } - - // Create Page object - final Page page = new Page<>(); - page.setPageNumber(pageNo); - page.setPagesAvailable(pageCount); - page.setTotalCount(rowCountInt); - - if (pageNo > pageCount) { - return page; - } - - List result = jdbcTemplate.query(sqlFetchRows, args, rowMapper); - for (E item : result) { - page.getPageItems().add(item); - } - return page; + return doFetchPage(sqlCountRows, args, sqlFetchRows, args, pageNo, pageSize, rowMapper); } @Override public Page fetchPageLimit(final String sqlCountRows, final String sqlFetchRows, final Object[] args, final int pageNo, final int pageSize, final RowMapper rowMapper) { - if (pageNo <= 0 || pageSize <= 0) { - throw new IllegalArgumentException("pageNo and pageSize must be greater than zero"); - } - // Query the total number of current records - Integer rowCountInt = jdbcTemplate.queryForObject(sqlCountRows, Integer.class); - if (rowCountInt == null) { - throw new IllegalArgumentException("fetchPageLimit error"); - } - - // Compute pages count - int pageCount = rowCountInt / pageSize; - if (rowCountInt > pageSize * pageCount) { - pageCount++; - } - - // Create Page object - final Page page = new Page<>(); - page.setPageNumber(pageNo); - page.setPagesAvailable(pageCount); - page.setTotalCount(rowCountInt); - - if (pageNo > pageCount) { - return page; - } - - List result = jdbcTemplate.query(sqlFetchRows, args, rowMapper); - for (E item : result) { - page.getPageItems().add(item); - } - return page; + return doFetchPage(sqlCountRows, null, sqlFetchRows, args, pageNo, pageSize, rowMapper); } @Override @@ -137,12 +78,48 @@ public Page fetchPageLimit(MapperResult countMapperResult, MapperResult mapperRe @Override public Page fetchPageLimit(final String sqlCountRows, final Object[] args1, final String sqlFetchRows, final Object[] args2, final int pageNo, final int pageSize, final RowMapper rowMapper) { + return doFetchPage(sqlCountRows, args1, sqlFetchRows, args2, pageNo, pageSize, rowMapper); + } + + @Override + public Page fetchPageLimit(final String sqlFetchRows, final Object[] args, final int pageNo, final int pageSize, + final RowMapper rowMapper) { + checkPageInfo(pageNo, pageSize); + // Create Page object + final Page page = new Page<>(); + List result = jdbcTemplate.query(sqlFetchRows, args, rowMapper); + for (E item : result) { + page.getPageItems().add(item); + } + return page; + } + + @Override + public void updateLimit(final String sql, final Object[] args) { + try { + jdbcTemplate.update(sql, args); + } finally { + EmbeddedStorageContextHolder.cleanAllContext(); + } + } + + private void checkPageInfo(final int pageNo, final int pageSize) { if (pageNo <= 0 || pageSize <= 0) { throw new IllegalArgumentException("pageNo and pageSize must be greater than zero"); } + } + + private Page doFetchPage(final String sqlCountRows, final Object[] countAgrs, final String sqlFetchRows, + final Object[] fetchArgs, final int pageNo, final int pageSize, final RowMapper rowMapper) { + checkPageInfo(pageNo, pageSize); // Query the total number of current records - Integer rowCountInt = jdbcTemplate.queryForObject(sqlCountRows, args1, Integer.class); - if (rowCountInt == null) { + Integer rowCountInt = null; + if (null != countAgrs) { + rowCountInt = jdbcTemplate.queryForObject(sqlCountRows, countAgrs, Integer.class); + } else { + rowCountInt = jdbcTemplate.queryForObject(sqlCountRows, Integer.class); + } + if (null == rowCountInt) { throw new IllegalArgumentException("fetchPageLimit error"); } @@ -161,52 +138,10 @@ public Page fetchPageLimit(final String sqlCountRows, final Object[] args1, f if (pageNo > pageCount) { return page; } - List result = jdbcTemplate.query(sqlFetchRows, args2, rowMapper); - for (E item : result) { - page.getPageItems().add(item); - } - return page; - } - - @Override - public Page fetchPageLimit(final String sqlFetchRows, final Object[] args, final int pageNo, final int pageSize, - final RowMapper rowMapper) { - if (pageNo <= 0 || pageSize <= 0) { - throw new IllegalArgumentException("pageNo and pageSize must be greater than zero"); - } - // Create Page object - final Page page = new Page<>(); - List result = jdbcTemplate.query(sqlFetchRows, args, rowMapper); + List result = jdbcTemplate.query(sqlFetchRows, fetchArgs, rowMapper); for (E item : result) { page.getPageItems().add(item); } return page; } - - @Override - public void updateLimit(final String sql, final Object[] args) { - try { - jdbcTemplate.update(sql, args); - } finally { - EmbeddedStorageContextHolder.cleanAllContext(); - } - } - - /** - * Update limit with response. - * - * @param sql sql - * @param args args - * @return update row count - */ - public int updateLimitWithResponse(final String sql, final Object[] args) { - String sqlUpdate = sql; - - try { - return jdbcTemplate.update(sqlUpdate, args); - } finally { - EmbeddedStorageContextHolder.cleanAllContext(); - } - } - } diff --git a/persistence/src/main/java/com/alibaba/nacos/persistence/utils/ConnectionCheckUtil.java b/persistence/src/main/java/com/alibaba/nacos/persistence/utils/ConnectionCheckUtil.java index 77c55f5ba5c..108a0003f90 100644 --- a/persistence/src/main/java/com/alibaba/nacos/persistence/utils/ConnectionCheckUtil.java +++ b/persistence/src/main/java/com/alibaba/nacos/persistence/utils/ConnectionCheckUtil.java @@ -17,8 +17,6 @@ package com.alibaba.nacos.persistence.utils; import com.zaxxer.hikari.HikariDataSource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * DataSource Connection CheckUtil. @@ -27,28 +25,16 @@ */ public class ConnectionCheckUtil { - private static final Logger LOGGER = LoggerFactory.getLogger(ConnectionCheckUtil.class); - /** * check HikariDataSource connection ,avoid [no datasource set] text. * * @param ds HikariDataSource object */ public static void checkDataSourceConnection(HikariDataSource ds) { - java.sql.Connection connection = null; - try { - connection = ds.getConnection(); + try (java.sql.Connection connection = ds.getConnection()) { + connection.isClosed(); } catch (Exception e) { throw new RuntimeException(e); - } finally { - if (connection != null) { - try { - connection.close(); - } catch (Exception e) { - LOGGER.error(e.getMessage(), e); - } - } } } - } diff --git a/persistence/src/test/java/com/alibaba/nacos/persistence/configuration/DatasourceConfigurationTest.java b/persistence/src/test/java/com/alibaba/nacos/persistence/configuration/DatasourceConfigurationTest.java new file mode 100644 index 00000000000..544f0ca3f40 --- /dev/null +++ b/persistence/src/test/java/com/alibaba/nacos/persistence/configuration/DatasourceConfigurationTest.java @@ -0,0 +1,133 @@ +/* + * Copyright 1999-2023 Alibaba Group Holding Ltd. + * + * Licensed 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 com.alibaba.nacos.persistence.configuration; + +import com.alibaba.nacos.persistence.constants.PersistenceConstant; +import com.alibaba.nacos.sys.env.EnvUtil; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.mock.env.MockEnvironment; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@ExtendWith(MockitoExtension.class) +class DatasourceConfigurationTest { + + @Mock + ConfigurableApplicationContext context; + + DatasourceConfiguration datasourceConfiguration; + + MockEnvironment environment; + + @BeforeEach + void setUp() { + environment = new MockEnvironment(); + EnvUtil.setEnvironment(environment); + datasourceConfiguration = new DatasourceConfiguration(); + DatasourceConfiguration.useExternalDB = false; + DatasourceConfiguration.embeddedStorage = true; + } + + @AfterEach + void tearDown() { + DatasourceConfiguration.useExternalDB = false; + DatasourceConfiguration.embeddedStorage = true; + EnvUtil.setIsStandalone(true); + EnvUtil.setEnvironment(null); + System.clearProperty(PersistenceConstant.EMBEDDED_STORAGE); + } + + @Test + void testInitializeForEmptyDatasourceForStandaloneMode() { + datasourceConfiguration.initialize(context); + assertTrue(DatasourceConfiguration.isEmbeddedStorage()); + assertFalse(DatasourceConfiguration.isUseExternalDB()); + } + + @Test + void testInitializeForEmptyDatasourceForClusterMode() { + EnvUtil.setIsStandalone(false); + DatasourceConfiguration.embeddedStorage = false; + datasourceConfiguration.initialize(context); + assertFalse(DatasourceConfiguration.isEmbeddedStorage()); + assertTrue(DatasourceConfiguration.isUseExternalDB()); + } + + @Test + void testInitializeForDerbyForStandaloneMode() { + environment.setProperty(PersistenceConstant.DATASOURCE_PLATFORM_PROPERTY, PersistenceConstant.DERBY); + System.setProperty(PersistenceConstant.EMBEDDED_STORAGE, "true"); + datasourceConfiguration.initialize(context); + assertTrue(DatasourceConfiguration.isEmbeddedStorage()); + assertFalse(DatasourceConfiguration.isUseExternalDB()); + } + + @Test + void testInitializeForDerbyForClusterMode() { + EnvUtil.setIsStandalone(false); + DatasourceConfiguration.embeddedStorage = false; + System.setProperty(PersistenceConstant.EMBEDDED_STORAGE, "true"); + environment.setProperty(PersistenceConstant.DATASOURCE_PLATFORM_PROPERTY, PersistenceConstant.DERBY); + datasourceConfiguration.initialize(context); + assertTrue(DatasourceConfiguration.isEmbeddedStorage()); + assertFalse(DatasourceConfiguration.isUseExternalDB()); + } + + @Test + void testInitializeForMySqlForStandaloneMode() { + environment.setProperty(PersistenceConstant.DATASOURCE_PLATFORM_PROPERTY, PersistenceConstant.MYSQL); + datasourceConfiguration.initialize(context); + assertFalse(DatasourceConfiguration.isEmbeddedStorage()); + assertTrue(DatasourceConfiguration.isUseExternalDB()); + + } + + @Test + void testInitializeForMySqlForClusterMode() { + EnvUtil.setIsStandalone(false); + DatasourceConfiguration.embeddedStorage = false; + environment.setProperty(PersistenceConstant.DATASOURCE_PLATFORM_PROPERTY, PersistenceConstant.MYSQL); + datasourceConfiguration.initialize(context); + assertFalse(DatasourceConfiguration.isEmbeddedStorage()); + assertTrue(DatasourceConfiguration.isUseExternalDB()); + } + + @Test + void testInitializeForPgSqlForStandaloneMode() { + environment.setProperty(PersistenceConstant.DATASOURCE_PLATFORM_PROPERTY, "postgresql"); + datasourceConfiguration.initialize(context); + assertFalse(DatasourceConfiguration.isEmbeddedStorage()); + assertTrue(DatasourceConfiguration.isUseExternalDB()); + } + + @Test + void testInitializeForPgSqlForClusterMode() { + EnvUtil.setIsStandalone(false); + DatasourceConfiguration.embeddedStorage = false; + environment.setProperty(PersistenceConstant.DATASOURCE_PLATFORM_PROPERTY, "postgresql"); + datasourceConfiguration.initialize(context); + assertFalse(DatasourceConfiguration.isEmbeddedStorage()); + assertTrue(DatasourceConfiguration.isUseExternalDB()); + } +} \ No newline at end of file diff --git a/persistence/src/test/java/com/alibaba/nacos/persistence/datasource/DynamicDataSourceTest.java b/persistence/src/test/java/com/alibaba/nacos/persistence/datasource/DynamicDataSourceTest.java index 6bf4c37c669..e1932d155d0 100644 --- a/persistence/src/test/java/com/alibaba/nacos/persistence/datasource/DynamicDataSourceTest.java +++ b/persistence/src/test/java/com/alibaba/nacos/persistence/datasource/DynamicDataSourceTest.java @@ -17,15 +17,19 @@ package com.alibaba.nacos.persistence.datasource; import com.alibaba.nacos.persistence.configuration.DatasourceConfiguration; +import com.alibaba.nacos.sys.env.EnvUtil; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.mock.env.MockEnvironment; import org.springframework.test.util.ReflectionTestUtils; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertThrows; @ExtendWith(MockitoExtension.class) class DynamicDataSourceTest { @@ -41,18 +45,45 @@ class DynamicDataSourceTest { @BeforeEach void setUp() { + EnvUtil.setEnvironment(new MockEnvironment()); dataSource = DynamicDataSource.getInstance(); + } + + @AfterEach + void tearDown() { + DatasourceConfiguration.setEmbeddedStorage(true); + DatasourceConfiguration.setUseExternalDB(false); + ReflectionTestUtils.setField(dataSource, "localDataSourceService", null); + ReflectionTestUtils.setField(dataSource, "basicDataSourceService", null); + EnvUtil.setEnvironment(null); + } + + @Test + void testGetDataSourceWithAlreadyInitialized() { ReflectionTestUtils.setField(dataSource, "localDataSourceService", localDataSourceService); ReflectionTestUtils.setField(dataSource, "basicDataSourceService", basicDataSourceService); + DatasourceConfiguration.setEmbeddedStorage(true); + assertInstanceOf(LocalDataSourceServiceImpl.class, dataSource.getDataSource()); + + DatasourceConfiguration.setEmbeddedStorage(false); + assertInstanceOf(ExternalDataSourceServiceImpl.class, dataSource.getDataSource()); } @Test - void testGetDataSource() { + void testInitWithEmbeddedStorage() { DatasourceConfiguration.setEmbeddedStorage(true); - assertTrue(dataSource.getDataSource() instanceof LocalDataSourceServiceImpl); - + assertInstanceOf(LocalDataSourceServiceImpl.class, dataSource.getDataSource()); + } + + @Test + void testInitWithExternalStorage() { DatasourceConfiguration.setEmbeddedStorage(false); - assertTrue(dataSource.getDataSource() instanceof ExternalDataSourceServiceImpl); + assertInstanceOf(ExternalDataSourceServiceImpl.class, dataSource.getDataSource()); } + @Test + void testInitWithException() { + EnvUtil.setEnvironment(null); + assertThrows(RuntimeException.class, () -> dataSource.getDataSource()); + } } diff --git a/persistence/src/test/java/com/alibaba/nacos/persistence/datasource/ExternalDataSourceServiceImplTest.java b/persistence/src/test/java/com/alibaba/nacos/persistence/datasource/ExternalDataSourceServiceImplTest.java index 5c41a0ca991..630b3a90394 100644 --- a/persistence/src/test/java/com/alibaba/nacos/persistence/datasource/ExternalDataSourceServiceImplTest.java +++ b/persistence/src/test/java/com/alibaba/nacos/persistence/datasource/ExternalDataSourceServiceImplTest.java @@ -16,6 +16,9 @@ package com.alibaba.nacos.persistence.datasource; +import com.alibaba.nacos.persistence.configuration.DatasourceConfiguration; +import com.alibaba.nacos.persistence.exception.NJdbcException; +import com.alibaba.nacos.sys.env.EnvUtil; import com.zaxxer.hikari.HikariDataSource; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -24,21 +27,31 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.jdbc.CannotGetJdbcConnectionException; import org.springframework.jdbc.UncategorizedSQLException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.mock.env.MockEnvironment; import org.springframework.test.util.ReflectionTestUtils; import org.springframework.transaction.support.TransactionTemplate; +import javax.sql.DataSource; import java.sql.SQLException; import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) @@ -75,34 +88,138 @@ void setUp() { ReflectionTestUtils.setField(service, "dataSourceList", dataSourceList); } + @Test + void testInit() { + try { + MockEnvironment environment = new MockEnvironment(); + EnvUtil.setEnvironment(environment); + environment.setProperty("db.num", "2"); + environment.setProperty("db.user", "user"); + environment.setProperty("db.password", "password"); + environment.setProperty("db.url.0", "1.1.1.1"); + environment.setProperty("db.url.1", "2.2.2.2"); + environment.setProperty("db.pool.config.driverClassName", + "com.alibaba.nacos.persistence.datasource.mock.MockDriver"); + DatasourceConfiguration.setUseExternalDB(true); + ExternalDataSourceServiceImpl service1 = new ExternalDataSourceServiceImpl(); + assertDoesNotThrow(service1::init); + assertEquals("", service1.getDataSourceType()); + assertEquals("1.1.1.1", service1.getCurrentDbUrl()); + assertNotNull(service1.getJdbcTemplate()); + assertNotNull(service1.getTransactionTemplate()); + } finally { + DatasourceConfiguration.setUseExternalDB(false); + EnvUtil.setEnvironment(null); + } + } + + @Test + void testInitInvalidConfig() { + try { + MockEnvironment environment = new MockEnvironment(); + EnvUtil.setEnvironment(environment); + DatasourceConfiguration.setUseExternalDB(true); + ExternalDataSourceServiceImpl service1 = new ExternalDataSourceServiceImpl(); + assertThrows(RuntimeException.class, service1::init); + } finally { + DatasourceConfiguration.setUseExternalDB(false); + EnvUtil.setEnvironment(null); + } + } + + @Test + void testReload() { + try { + MockEnvironment environment = new MockEnvironment(); + EnvUtil.setEnvironment(environment); + environment.setProperty("db.num", "1"); + environment.setProperty("db.user", "user"); + environment.setProperty("db.password", "password"); + environment.setProperty("db.url.0", "1.1.1.1"); + environment.setProperty("db.pool.config.driverClassName", + "com.alibaba.nacos.persistence.datasource.mock.MockDriver"); + DatasourceConfiguration.setUseExternalDB(true); + HikariDataSource dataSource = mock(HikariDataSource.class); + JdbcTemplate oldJt = mock(JdbcTemplate.class); + ReflectionTestUtils.setField(service, "testJtList", Collections.singletonList(oldJt)); + ReflectionTestUtils.setField(service, "dataSourceList", Collections.singletonList(dataSource)); + assertDoesNotThrow(service::reload); + verify(jt).setDataSource(any(DataSource.class)); + verify(oldJt).setDataSource(null); + verify(dataSource).close(); + } finally { + DatasourceConfiguration.setUseExternalDB(false); + EnvUtil.setEnvironment(null); + } + } + @Test void testCheckMasterWritable() { - when(testMasterWritableJT.queryForObject(eq(" SELECT @@read_only "), eq(Integer.class))).thenReturn(0); assertTrue(service.checkMasterWritable()); } + @Test + void testCheckMasterWritableWithoutResult() { + when(testMasterWritableJT.queryForObject(eq(" SELECT @@read_only "), eq(Integer.class))).thenReturn(null); + assertFalse(service.checkMasterWritable()); + } + + @Test + void testCheckMasterWritableWithException() { + when(testMasterWritableJT.queryForObject(eq(" SELECT @@read_only "), eq(Integer.class))).thenThrow( + new CannotGetJdbcConnectionException("test")); + assertFalse(service.checkMasterWritable()); + } + @Test void testGetCurrentDbUrl() { - HikariDataSource bds = new HikariDataSource(); bds.setJdbcUrl("test.jdbc.url"); when(jt.getDataSource()).thenReturn(bds); - assertEquals("test.jdbc.url", service.getCurrentDbUrl()); } + @Test + void testGetCurrentDbUrlWithoutDatasource() { + assertEquals("", service.getCurrentDbUrl()); + } + @Test void testGetHealth() { - List isHealthList = new ArrayList<>(); ReflectionTestUtils.setField(service, "isHealthList", isHealthList); assertEquals("UP", service.getHealth()); } + @Test + void testGetHealthWithMasterDown() { + HikariDataSource dataSource = mock(HikariDataSource.class); + when(dataSource.getJdbcUrl()).thenReturn("1.1.1.1"); + ReflectionTestUtils.setField(service, "dataSourceList", Collections.singletonList(dataSource)); + List isHealthList = new ArrayList<>(); + isHealthList.add(Boolean.FALSE); + ReflectionTestUtils.setField(service, "isHealthList", isHealthList); + assertEquals("DOWN:1.1.1.1", service.getHealth()); + } + + @Test + void testGetHealthWithSlaveDown() { + HikariDataSource dataSource = mock(HikariDataSource.class); + when(dataSource.getJdbcUrl()).thenReturn("2.2.2.2"); + List dataSourceList = new ArrayList<>(); + dataSourceList.add(null); + dataSourceList.add(dataSource); + ReflectionTestUtils.setField(service, "dataSourceList", dataSourceList); + List isHealthList = new ArrayList<>(); + isHealthList.add(Boolean.TRUE); + isHealthList.add(Boolean.FALSE); + ReflectionTestUtils.setField(service, "isHealthList", isHealthList); + assertEquals("WARN:2.2.2.2", service.getHealth()); + } + @Test void testCheckDbHealthTaskRun() { - List testJtList = new ArrayList<>(); testJtList.add(jt); ReflectionTestUtils.setField(service, "testJtList", testJtList); @@ -142,10 +259,37 @@ void testCheckDbHealthTaskRunWhenSqlException() { isHealthList.add(Boolean.FALSE); ReflectionTestUtils.setField(service, "isHealthList", isHealthList); - when(jt.queryForMap(anyString())).thenThrow(new UncategorizedSQLException("Expected exception", "", new SQLException())); + when(jt.queryForMap(anyString())).thenThrow( + new UncategorizedSQLException("Expected exception", "", new SQLException())); + service.new CheckDbHealthTask().run(); + assertEquals(1, isHealthList.size()); + assertFalse(isHealthList.get(0)); + } + + @Test + void testCheckDbHealthTaskRunWhenSqlExceptionForSlave() { + List testJtList = new ArrayList<>(); + testJtList.add(jt); + ReflectionTestUtils.setField(service, "testJtList", testJtList); + + List isHealthList = new ArrayList<>(); + isHealthList.add(Boolean.FALSE); + ReflectionTestUtils.setField(service, "isHealthList", isHealthList); + ReflectionTestUtils.setField(service, "masterIndex", 1); + + when(jt.queryForMap(anyString())).thenThrow( + new UncategorizedSQLException("Expected exception", "", new SQLException())); service.new CheckDbHealthTask().run(); assertEquals(1, isHealthList.size()); assertFalse(isHealthList.get(0)); } + @Test + void testMasterSelectWithException() { + HikariDataSource dataSource = mock(HikariDataSource.class); + ReflectionTestUtils.setField(service, "dataSourceList", Collections.singletonList(dataSource)); + when(testMasterJT.update("DELETE FROM config_info WHERE data_id='com.alibaba.nacos.testMasterDB'")).thenThrow( + new NJdbcException("test")); + assertDoesNotThrow(() -> service.new SelectMasterTask().run()); + } } diff --git a/persistence/src/test/java/com/alibaba/nacos/persistence/datasource/LocalDataSourceServiceImplTest.java b/persistence/src/test/java/com/alibaba/nacos/persistence/datasource/LocalDataSourceServiceImplTest.java index dd8dd298fc4..b5a87d81a60 100644 --- a/persistence/src/test/java/com/alibaba/nacos/persistence/datasource/LocalDataSourceServiceImplTest.java +++ b/persistence/src/test/java/com/alibaba/nacos/persistence/datasource/LocalDataSourceServiceImplTest.java @@ -16,6 +16,9 @@ package com.alibaba.nacos.persistence.datasource; +import com.alibaba.nacos.api.exception.runtime.NacosRuntimeException; +import com.alibaba.nacos.persistence.configuration.DatasourceConfiguration; +import com.alibaba.nacos.sys.env.EnvUtil; import com.zaxxer.hikari.HikariDataSource; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -24,11 +27,22 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.mock.env.MockEnvironment; import org.springframework.test.util.ReflectionTestUtils; import org.springframework.transaction.support.TransactionTemplate; +import javax.sql.DataSource; +import java.sql.SQLException; +import java.util.concurrent.Callable; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertThrowsExactly; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) @@ -45,14 +59,79 @@ class LocalDataSourceServiceImplTest { @BeforeEach void setUp() { + DatasourceConfiguration.setUseExternalDB(false); service = new LocalDataSourceServiceImpl(); ReflectionTestUtils.setField(service, "jt", jt); ReflectionTestUtils.setField(service, "tjt", tjt); } + @Test + void testInitWhenUseExternalDB() throws Exception { + try { + DatasourceConfiguration.setUseExternalDB(true); + EnvUtil.setEnvironment(null); + LocalDataSourceServiceImpl service1 = new LocalDataSourceServiceImpl(); + assertDoesNotThrow(service1::init); + } finally { + DatasourceConfiguration.setUseExternalDB(false); + } + } + + @Test + void testInit() throws Exception { + try { + EnvUtil.setEnvironment(new MockEnvironment()); + LocalDataSourceServiceImpl service1 = new LocalDataSourceServiceImpl(); + assertDoesNotThrow(service1::init); + assertNotNull(service1.getJdbcTemplate()); + assertNotNull(service1.getTransactionTemplate()); + assertEquals("derby", service1.getDataSourceType()); + } finally { + EnvUtil.setEnvironment(null); + } + } + + @Test + void testReloadWithNullDatasource() { + assertThrowsExactly(RuntimeException.class, service::reload, "datasource is null"); + } + + @Test + void testReloadWithException() throws SQLException { + DataSource ds = mock(DataSource.class); + when(jt.getDataSource()).thenReturn(ds); + when(ds.getConnection()).thenThrow(new SQLException()); + assertThrows(NacosRuntimeException.class, service::reload); + } + + @Test + void testCleanAndReopen() throws Exception { + try { + EnvUtil.setEnvironment(new MockEnvironment()); + LocalDataSourceServiceImpl service1 = new LocalDataSourceServiceImpl(); + assertDoesNotThrow(service1::init); + assertDoesNotThrow(service1::cleanAndReopenDerby); + } finally { + EnvUtil.setEnvironment(null); + } + } + + @Test + void testRestoreDerby() throws Exception { + try { + EnvUtil.setEnvironment(new MockEnvironment()); + LocalDataSourceServiceImpl service1 = new LocalDataSourceServiceImpl(); + assertDoesNotThrow(service1::init); + Callable callback = mock(Callable.class); + assertDoesNotThrow(() -> service1.restoreDerby(service1.getCurrentDbUrl(), callback)); + verify(callback).call(); + } finally { + EnvUtil.setEnvironment(null); + } + } + @Test void testGetDataSource() { - HikariDataSource dataSource = new HikariDataSource(); dataSource.setJdbcUrl("test.jdbc.url"); when(jt.getDataSource()).thenReturn(dataSource); @@ -61,13 +140,11 @@ void testGetDataSource() { @Test void testCheckMasterWritable() { - assertTrue(service.checkMasterWritable()); } @Test void testSetAndGetHealth() { - service.setHealthStatus("DOWN"); assertEquals("DOWN", service.getHealth()); diff --git a/persistence/src/test/java/com/alibaba/nacos/persistence/datasource/mock/MockConnection.java b/persistence/src/test/java/com/alibaba/nacos/persistence/datasource/mock/MockConnection.java new file mode 100644 index 00000000000..d2088b62a66 --- /dev/null +++ b/persistence/src/test/java/com/alibaba/nacos/persistence/datasource/mock/MockConnection.java @@ -0,0 +1,314 @@ +/* + * Copyright 1999-2023 Alibaba Group Holding Ltd. + * + * Licensed 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 com.alibaba.nacos.persistence.datasource.mock; + +import java.sql.Array; +import java.sql.Blob; +import java.sql.CallableStatement; +import java.sql.Clob; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.NClob; +import java.sql.PreparedStatement; +import java.sql.SQLClientInfoException; +import java.sql.SQLException; +import java.sql.SQLWarning; +import java.sql.SQLXML; +import java.sql.Savepoint; +import java.sql.Statement; +import java.sql.Struct; +import java.util.Collections; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.Executor; + +public class MockConnection implements Connection { + + @Override + public String nativeSQL(String sql) throws SQLException { + return ""; + } + + @Override + public void setAutoCommit(boolean autoCommit) throws SQLException { + + } + + @Override + public boolean getAutoCommit() throws SQLException { + return false; + } + + @Override + public void commit() throws SQLException { + + } + + @Override + public void rollback() throws SQLException { + + } + + @Override + public void rollback(Savepoint savepoint) throws SQLException { + + } + + @Override + public void close() throws SQLException { + + } + + @Override + public boolean isClosed() throws SQLException { + return false; + } + + @Override + public DatabaseMetaData getMetaData() throws SQLException { + return null; + } + + @Override + public void setReadOnly(boolean readOnly) throws SQLException { + + } + + @Override + public boolean isReadOnly() throws SQLException { + return false; + } + + @Override + public void setCatalog(String catalog) throws SQLException { + + } + + @Override + public String getCatalog() throws SQLException { + return ""; + } + + @Override + public void setTransactionIsolation(int level) throws SQLException { + + } + + @Override + public int getTransactionIsolation() throws SQLException { + return 0; + } + + @Override + public SQLWarning getWarnings() throws SQLException { + return null; + } + + @Override + public void clearWarnings() throws SQLException { + + } + + @Override + public Statement createStatement() throws SQLException { + return new MockStatement(); + } + + @Override + public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException { + return new MockStatement(); + } + + @Override + public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) + throws SQLException { + return new MockStatement(); + } + + @Override + public CallableStatement prepareCall(String sql) throws SQLException { + return null; + } + + @Override + public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { + return null; + } + + @Override + public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, + int resultSetHoldability) throws SQLException { + return null; + } + + @Override + public Map> getTypeMap() throws SQLException { + return Collections.emptyMap(); + } + + @Override + public void setTypeMap(Map> map) throws SQLException { + + } + + @Override + public void setHoldability(int holdability) throws SQLException { + + } + + @Override + public int getHoldability() throws SQLException { + return 0; + } + + @Override + public Savepoint setSavepoint() throws SQLException { + return null; + } + + @Override + public Savepoint setSavepoint(String name) throws SQLException { + return null; + } + + @Override + public void releaseSavepoint(Savepoint savepoint) throws SQLException { + + } + + @Override + public PreparedStatement prepareStatement(String sql) throws SQLException { + return new MockPreparedStatement(); + } + + @Override + public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) + throws SQLException { + return new MockPreparedStatement(); + } + + @Override + public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, + int resultSetHoldability) throws SQLException { + return new MockPreparedStatement(); + } + + @Override + public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException { + return new MockPreparedStatement(); + } + + @Override + public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException { + return new MockPreparedStatement(); + } + + @Override + public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException { + return new MockPreparedStatement(); + } + + @Override + public Clob createClob() throws SQLException { + return null; + } + + @Override + public Blob createBlob() throws SQLException { + return null; + } + + @Override + public NClob createNClob() throws SQLException { + return null; + } + + @Override + public SQLXML createSQLXML() throws SQLException { + return null; + } + + @Override + public boolean isValid(int timeout) throws SQLException { + return false; + } + + @Override + public void setClientInfo(String name, String value) throws SQLClientInfoException { + + } + + @Override + public void setClientInfo(Properties properties) throws SQLClientInfoException { + + } + + @Override + public String getClientInfo(String name) throws SQLException { + return ""; + } + + @Override + public Properties getClientInfo() throws SQLException { + return null; + } + + @Override + public Array createArrayOf(String typeName, Object[] elements) throws SQLException { + return null; + } + + @Override + public Struct createStruct(String typeName, Object[] attributes) throws SQLException { + return null; + } + + @Override + public void setSchema(String schema) throws SQLException { + + } + + @Override + public String getSchema() throws SQLException { + return ""; + } + + @Override + public void abort(Executor executor) throws SQLException { + + } + + @Override + public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException { + + } + + @Override + public int getNetworkTimeout() throws SQLException { + return 0; + } + + @Override + public T unwrap(Class iface) throws SQLException { + return null; + } + + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + return false; + } +} diff --git a/persistence/src/test/java/com/alibaba/nacos/persistence/datasource/mock/MockDriver.java b/persistence/src/test/java/com/alibaba/nacos/persistence/datasource/mock/MockDriver.java new file mode 100644 index 00000000000..2cbb8a179d9 --- /dev/null +++ b/persistence/src/test/java/com/alibaba/nacos/persistence/datasource/mock/MockDriver.java @@ -0,0 +1,63 @@ +/* + * Copyright 1999-2023 Alibaba Group Holding Ltd. + * + * Licensed 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 com.alibaba.nacos.persistence.datasource.mock; + +import java.sql.Connection; +import java.sql.Driver; +import java.sql.DriverPropertyInfo; +import java.sql.SQLException; +import java.sql.SQLFeatureNotSupportedException; +import java.util.Properties; +import java.util.logging.Logger; + +public class MockDriver implements Driver { + + @Override + public Connection connect(String url, Properties info) throws SQLException { + return new MockConnection(); + } + + @Override + public boolean acceptsURL(String url) throws SQLException { + return true; + } + + @Override + public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException { + return new DriverPropertyInfo[0]; + } + + @Override + public int getMajorVersion() { + return 0; + } + + @Override + public int getMinorVersion() { + return 0; + } + + @Override + public boolean jdbcCompliant() { + return false; + } + + @Override + public Logger getParentLogger() throws SQLFeatureNotSupportedException { + return null; + } +} diff --git a/persistence/src/test/java/com/alibaba/nacos/persistence/datasource/mock/MockPreparedStatement.java b/persistence/src/test/java/com/alibaba/nacos/persistence/datasource/mock/MockPreparedStatement.java new file mode 100644 index 00000000000..f257a58a1ef --- /dev/null +++ b/persistence/src/test/java/com/alibaba/nacos/persistence/datasource/mock/MockPreparedStatement.java @@ -0,0 +1,539 @@ +/* + * Copyright 1999-2023 Alibaba Group Holding Ltd. + * + * Licensed 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 com.alibaba.nacos.persistence.datasource.mock; + +import java.io.InputStream; +import java.io.Reader; +import java.math.BigDecimal; +import java.net.URL; +import java.sql.Array; +import java.sql.Blob; +import java.sql.Clob; +import java.sql.Connection; +import java.sql.Date; +import java.sql.NClob; +import java.sql.ParameterMetaData; +import java.sql.PreparedStatement; +import java.sql.Ref; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.RowId; +import java.sql.SQLException; +import java.sql.SQLWarning; +import java.sql.SQLXML; +import java.sql.Time; +import java.sql.Timestamp; +import java.util.Calendar; + +@SuppressWarnings("checkstyle:OverloadMethodsDeclarationOrder") +public class MockPreparedStatement implements PreparedStatement { + + @Override + public ResultSet executeQuery() throws SQLException { + return new MockResultSet(); + } + + @Override + public int executeUpdate() throws SQLException { + return 0; + } + + @Override + public void setNull(int parameterIndex, int sqlType) throws SQLException { + + } + + @Override + public void setBoolean(int parameterIndex, boolean x) throws SQLException { + + } + + @Override + public void setByte(int parameterIndex, byte x) throws SQLException { + + } + + @Override + public void setShort(int parameterIndex, short x) throws SQLException { + + } + + @Override + public void setInt(int parameterIndex, int x) throws SQLException { + + } + + @Override + public void setLong(int parameterIndex, long x) throws SQLException { + + } + + @Override + public void setFloat(int parameterIndex, float x) throws SQLException { + + } + + @Override + public void setDouble(int parameterIndex, double x) throws SQLException { + + } + + @Override + public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException { + + } + + @Override + public void setString(int parameterIndex, String x) throws SQLException { + + } + + @Override + public void setBytes(int parameterIndex, byte[] x) throws SQLException { + + } + + @Override + public void setDate(int parameterIndex, Date x) throws SQLException { + + } + + @Override + public void setTime(int parameterIndex, Time x) throws SQLException { + + } + + @Override + public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException { + + } + + @Override + public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException { + + } + + @Override + public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException { + + } + + @Override + public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException { + + } + + @Override + public void clearParameters() throws SQLException { + + } + + @Override + public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException { + + } + + @Override + public void setObject(int parameterIndex, Object x) throws SQLException { + + } + + @Override + public boolean execute() throws SQLException { + return false; + } + + @Override + public void addBatch() throws SQLException { + + } + + @Override + public void setCharacterStream(int parameterIndex, Reader reader, int length) throws SQLException { + + } + + @Override + public void setRef(int parameterIndex, Ref x) throws SQLException { + + } + + @Override + public void setBlob(int parameterIndex, Blob x) throws SQLException { + + } + + @Override + public void setClob(int parameterIndex, Clob x) throws SQLException { + + } + + @Override + public void setArray(int parameterIndex, Array x) throws SQLException { + + } + + @Override + public ResultSetMetaData getMetaData() throws SQLException { + return null; + } + + @Override + public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException { + + } + + @Override + public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException { + + } + + @Override + public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException { + + } + + @Override + public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException { + + } + + @Override + public void setURL(int parameterIndex, URL x) throws SQLException { + + } + + @Override + public ParameterMetaData getParameterMetaData() throws SQLException { + return null; + } + + @Override + public void setRowId(int parameterIndex, RowId x) throws SQLException { + + } + + @Override + public void setNString(int parameterIndex, String value) throws SQLException { + + } + + @Override + public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException { + + } + + @Override + public void setNClob(int parameterIndex, NClob value) throws SQLException { + + } + + @Override + public void setClob(int parameterIndex, Reader reader, long length) throws SQLException { + + } + + @Override + public void setBlob(int parameterIndex, InputStream inputStream, long length) throws SQLException { + + } + + @Override + public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException { + + } + + @Override + public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException { + + } + + @Override + public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) throws SQLException { + + } + + @Override + public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException { + + } + + @Override + public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException { + + } + + @Override + public void setCharacterStream(int parameterIndex, Reader reader, long length) throws SQLException { + + } + + @Override + public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException { + + } + + @Override + public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException { + + } + + @Override + public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException { + + } + + @Override + public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException { + + } + + @Override + public void setClob(int parameterIndex, Reader reader) throws SQLException { + + } + + @Override + public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException { + + } + + @Override + public void setNClob(int parameterIndex, Reader reader) throws SQLException { + + } + + @Override + public ResultSet executeQuery(String sql) throws SQLException { + return new MockResultSet(); + } + + @Override + public int executeUpdate(String sql) throws SQLException { + return 0; + } + + @Override + public void close() throws SQLException { + + } + + @Override + public int getMaxFieldSize() throws SQLException { + return 0; + } + + @Override + public void setMaxFieldSize(int max) throws SQLException { + + } + + @Override + public int getMaxRows() throws SQLException { + return 0; + } + + @Override + public void setMaxRows(int max) throws SQLException { + + } + + @Override + public void setEscapeProcessing(boolean enable) throws SQLException { + + } + + @Override + public int getQueryTimeout() throws SQLException { + return 0; + } + + @Override + public void setQueryTimeout(int seconds) throws SQLException { + + } + + @Override + public void cancel() throws SQLException { + + } + + @Override + public SQLWarning getWarnings() throws SQLException { + return null; + } + + @Override + public void clearWarnings() throws SQLException { + + } + + @Override + public void setCursorName(String name) throws SQLException { + + } + + @Override + public boolean execute(String sql) throws SQLException { + return false; + } + + @Override + public ResultSet getResultSet() throws SQLException { + return new MockResultSet(); + } + + @Override + public int getUpdateCount() throws SQLException { + return 0; + } + + @Override + public boolean getMoreResults() throws SQLException { + return false; + } + + @Override + public void setFetchDirection(int direction) throws SQLException { + + } + + @Override + public int getFetchDirection() throws SQLException { + return 0; + } + + @Override + public void setFetchSize(int rows) throws SQLException { + + } + + @Override + public int getFetchSize() throws SQLException { + return 0; + } + + @Override + public int getResultSetConcurrency() throws SQLException { + return 0; + } + + @Override + public int getResultSetType() throws SQLException { + return 0; + } + + @Override + public void addBatch(String sql) throws SQLException { + + } + + @Override + public void clearBatch() throws SQLException { + + } + + @Override + public int[] executeBatch() throws SQLException { + return new int[0]; + } + + @Override + public Connection getConnection() throws SQLException { + return null; + } + + @Override + public boolean getMoreResults(int current) throws SQLException { + return false; + } + + @Override + public ResultSet getGeneratedKeys() throws SQLException { + return new MockResultSet(); + } + + @Override + public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException { + return 0; + } + + @Override + public int executeUpdate(String sql, int[] columnIndexes) throws SQLException { + return 0; + } + + @Override + public int executeUpdate(String sql, String[] columnNames) throws SQLException { + return 0; + } + + @Override + public boolean execute(String sql, int autoGeneratedKeys) throws SQLException { + return false; + } + + @Override + public boolean execute(String sql, int[] columnIndexes) throws SQLException { + return false; + } + + @Override + public boolean execute(String sql, String[] columnNames) throws SQLException { + return false; + } + + @Override + public int getResultSetHoldability() throws SQLException { + return 0; + } + + @Override + public boolean isClosed() throws SQLException { + return false; + } + + @Override + public void setPoolable(boolean poolable) throws SQLException { + + } + + @Override + public boolean isPoolable() throws SQLException { + return false; + } + + @Override + public void closeOnCompletion() throws SQLException { + + } + + @Override + public boolean isCloseOnCompletion() throws SQLException { + return false; + } + + @Override + public T unwrap(Class iface) throws SQLException { + return null; + } + + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + return false; + } +} diff --git a/persistence/src/test/java/com/alibaba/nacos/persistence/datasource/mock/MockResultSet.java b/persistence/src/test/java/com/alibaba/nacos/persistence/datasource/mock/MockResultSet.java new file mode 100644 index 00000000000..697885e8f8b --- /dev/null +++ b/persistence/src/test/java/com/alibaba/nacos/persistence/datasource/mock/MockResultSet.java @@ -0,0 +1,998 @@ +/* + * Copyright 1999-2023 Alibaba Group Holding Ltd. + * + * Licensed 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 com.alibaba.nacos.persistence.datasource.mock; + +import java.io.InputStream; +import java.io.Reader; +import java.math.BigDecimal; +import java.net.URL; +import java.sql.Array; +import java.sql.Blob; +import java.sql.Clob; +import java.sql.Date; +import java.sql.NClob; +import java.sql.Ref; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.RowId; +import java.sql.SQLException; +import java.sql.SQLWarning; +import java.sql.SQLXML; +import java.sql.Statement; +import java.sql.Time; +import java.sql.Timestamp; +import java.util.Calendar; +import java.util.Map; + +@SuppressWarnings("checkstyle:OverloadMethodsDeclarationOrder") +public class MockResultSet implements ResultSet { + + @Override + public boolean next() throws SQLException { + return false; + } + + @Override + public void close() throws SQLException { + + } + + @Override + public boolean wasNull() throws SQLException { + return false; + } + + @Override + public String getString(int columnIndex) throws SQLException { + return ""; + } + + @Override + public boolean getBoolean(int columnIndex) throws SQLException { + return false; + } + + @Override + public byte getByte(int columnIndex) throws SQLException { + return 0; + } + + @Override + public short getShort(int columnIndex) throws SQLException { + return 0; + } + + @Override + public int getInt(int columnIndex) throws SQLException { + return 0; + } + + @Override + public long getLong(int columnIndex) throws SQLException { + return 0; + } + + @Override + public float getFloat(int columnIndex) throws SQLException { + return 0; + } + + @Override + public double getDouble(int columnIndex) throws SQLException { + return 0; + } + + @Override + public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException { + return null; + } + + @Override + public byte[] getBytes(int columnIndex) throws SQLException { + return new byte[0]; + } + + @Override + public Date getDate(int columnIndex) throws SQLException { + return null; + } + + @Override + public Time getTime(int columnIndex) throws SQLException { + return null; + } + + @Override + public Timestamp getTimestamp(int columnIndex) throws SQLException { + return null; + } + + @Override + public InputStream getAsciiStream(int columnIndex) throws SQLException { + return null; + } + + @Override + public InputStream getUnicodeStream(int columnIndex) throws SQLException { + return null; + } + + @Override + public InputStream getBinaryStream(int columnIndex) throws SQLException { + return null; + } + + @Override + public String getString(String columnLabel) throws SQLException { + return ""; + } + + @Override + public boolean getBoolean(String columnLabel) throws SQLException { + return false; + } + + @Override + public byte getByte(String columnLabel) throws SQLException { + return 0; + } + + @Override + public short getShort(String columnLabel) throws SQLException { + return 0; + } + + @Override + public int getInt(String columnLabel) throws SQLException { + return 0; + } + + @Override + public long getLong(String columnLabel) throws SQLException { + return 0; + } + + @Override + public float getFloat(String columnLabel) throws SQLException { + return 0; + } + + @Override + public double getDouble(String columnLabel) throws SQLException { + return 0; + } + + @Override + public BigDecimal getBigDecimal(String columnLabel, int scale) throws SQLException { + return null; + } + + @Override + public byte[] getBytes(String columnLabel) throws SQLException { + return new byte[0]; + } + + @Override + public Date getDate(String columnLabel) throws SQLException { + return null; + } + + @Override + public Time getTime(String columnLabel) throws SQLException { + return null; + } + + @Override + public Timestamp getTimestamp(String columnLabel) throws SQLException { + return null; + } + + @Override + public InputStream getAsciiStream(String columnLabel) throws SQLException { + return null; + } + + @Override + public InputStream getUnicodeStream(String columnLabel) throws SQLException { + return null; + } + + @Override + public InputStream getBinaryStream(String columnLabel) throws SQLException { + return null; + } + + @Override + public SQLWarning getWarnings() throws SQLException { + return null; + } + + @Override + public void clearWarnings() throws SQLException { + + } + + @Override + public String getCursorName() throws SQLException { + return ""; + } + + @Override + public ResultSetMetaData getMetaData() throws SQLException { + return null; + } + + @Override + public Object getObject(int columnIndex) throws SQLException { + return null; + } + + @Override + public Object getObject(String columnLabel) throws SQLException { + return null; + } + + @Override + public int findColumn(String columnLabel) throws SQLException { + return 0; + } + + @Override + public Reader getCharacterStream(int columnIndex) throws SQLException { + return null; + } + + @Override + public Reader getCharacterStream(String columnLabel) throws SQLException { + return null; + } + + @Override + public BigDecimal getBigDecimal(int columnIndex) throws SQLException { + return null; + } + + @Override + public BigDecimal getBigDecimal(String columnLabel) throws SQLException { + return null; + } + + @Override + public boolean isBeforeFirst() throws SQLException { + return false; + } + + @Override + public boolean isAfterLast() throws SQLException { + return false; + } + + @Override + public boolean isFirst() throws SQLException { + return false; + } + + @Override + public boolean isLast() throws SQLException { + return false; + } + + @Override + public void beforeFirst() throws SQLException { + + } + + @Override + public void afterLast() throws SQLException { + + } + + @Override + public boolean first() throws SQLException { + return false; + } + + @Override + public boolean last() throws SQLException { + return false; + } + + @Override + public int getRow() throws SQLException { + return 0; + } + + @Override + public boolean absolute(int row) throws SQLException { + return false; + } + + @Override + public boolean relative(int rows) throws SQLException { + return false; + } + + @Override + public boolean previous() throws SQLException { + return false; + } + + @Override + public void setFetchDirection(int direction) throws SQLException { + + } + + @Override + public int getFetchDirection() throws SQLException { + return 0; + } + + @Override + public void setFetchSize(int rows) throws SQLException { + + } + + @Override + public int getFetchSize() throws SQLException { + return 0; + } + + @Override + public int getType() throws SQLException { + return 0; + } + + @Override + public int getConcurrency() throws SQLException { + return 0; + } + + @Override + public boolean rowUpdated() throws SQLException { + return false; + } + + @Override + public boolean rowInserted() throws SQLException { + return false; + } + + @Override + public boolean rowDeleted() throws SQLException { + return false; + } + + @Override + public void updateNull(int columnIndex) throws SQLException { + + } + + @Override + public void updateBoolean(int columnIndex, boolean x) throws SQLException { + + } + + @Override + public void updateByte(int columnIndex, byte x) throws SQLException { + + } + + @Override + public void updateShort(int columnIndex, short x) throws SQLException { + + } + + @Override + public void updateInt(int columnIndex, int x) throws SQLException { + + } + + @Override + public void updateLong(int columnIndex, long x) throws SQLException { + + } + + @Override + public void updateFloat(int columnIndex, float x) throws SQLException { + + } + + @Override + public void updateDouble(int columnIndex, double x) throws SQLException { + + } + + @Override + public void updateBigDecimal(int columnIndex, BigDecimal x) throws SQLException { + + } + + @Override + public void updateString(int columnIndex, String x) throws SQLException { + + } + + @Override + public void updateBytes(int columnIndex, byte[] x) throws SQLException { + + } + + @Override + public void updateDate(int columnIndex, Date x) throws SQLException { + + } + + @Override + public void updateTime(int columnIndex, Time x) throws SQLException { + + } + + @Override + public void updateTimestamp(int columnIndex, Timestamp x) throws SQLException { + + } + + @Override + public void updateAsciiStream(int columnIndex, InputStream x, int length) throws SQLException { + + } + + @Override + public void updateBinaryStream(int columnIndex, InputStream x, int length) throws SQLException { + + } + + @Override + public void updateCharacterStream(int columnIndex, Reader x, int length) throws SQLException { + + } + + @Override + public void updateObject(int columnIndex, Object x, int scaleOrLength) throws SQLException { + + } + + @Override + public void updateObject(int columnIndex, Object x) throws SQLException { + + } + + @Override + public void updateNull(String columnLabel) throws SQLException { + + } + + @Override + public void updateBoolean(String columnLabel, boolean x) throws SQLException { + + } + + @Override + public void updateByte(String columnLabel, byte x) throws SQLException { + + } + + @Override + public void updateShort(String columnLabel, short x) throws SQLException { + + } + + @Override + public void updateInt(String columnLabel, int x) throws SQLException { + + } + + @Override + public void updateLong(String columnLabel, long x) throws SQLException { + + } + + @Override + public void updateFloat(String columnLabel, float x) throws SQLException { + + } + + @Override + public void updateDouble(String columnLabel, double x) throws SQLException { + + } + + @Override + public void updateBigDecimal(String columnLabel, BigDecimal x) throws SQLException { + + } + + @Override + public void updateString(String columnLabel, String x) throws SQLException { + + } + + @Override + public void updateBytes(String columnLabel, byte[] x) throws SQLException { + + } + + @Override + public void updateDate(String columnLabel, Date x) throws SQLException { + + } + + @Override + public void updateTime(String columnLabel, Time x) throws SQLException { + + } + + @Override + public void updateTimestamp(String columnLabel, Timestamp x) throws SQLException { + + } + + @Override + public void updateAsciiStream(String columnLabel, InputStream x, int length) throws SQLException { + + } + + @Override + public void updateBinaryStream(String columnLabel, InputStream x, int length) throws SQLException { + + } + + @Override + public void updateCharacterStream(String columnLabel, Reader reader, int length) throws SQLException { + + } + + @Override + public void updateObject(String columnLabel, Object x, int scaleOrLength) throws SQLException { + + } + + @Override + public void updateObject(String columnLabel, Object x) throws SQLException { + + } + + @Override + public void insertRow() throws SQLException { + + } + + @Override + public void updateRow() throws SQLException { + + } + + @Override + public void deleteRow() throws SQLException { + + } + + @Override + public void refreshRow() throws SQLException { + + } + + @Override + public void cancelRowUpdates() throws SQLException { + + } + + @Override + public void moveToInsertRow() throws SQLException { + + } + + @Override + public void moveToCurrentRow() throws SQLException { + + } + + @Override + public Statement getStatement() throws SQLException { + return null; + } + + @Override + public Object getObject(int columnIndex, Map> map) throws SQLException { + return null; + } + + @Override + public Ref getRef(int columnIndex) throws SQLException { + return null; + } + + @Override + public Blob getBlob(int columnIndex) throws SQLException { + return null; + } + + @Override + public Clob getClob(int columnIndex) throws SQLException { + return null; + } + + @Override + public Array getArray(int columnIndex) throws SQLException { + return null; + } + + @Override + public Object getObject(String columnLabel, Map> map) throws SQLException { + return null; + } + + @Override + public Ref getRef(String columnLabel) throws SQLException { + return null; + } + + @Override + public Blob getBlob(String columnLabel) throws SQLException { + return null; + } + + @Override + public Clob getClob(String columnLabel) throws SQLException { + return null; + } + + @Override + public Array getArray(String columnLabel) throws SQLException { + return null; + } + + @Override + public Date getDate(int columnIndex, Calendar cal) throws SQLException { + return null; + } + + @Override + public Date getDate(String columnLabel, Calendar cal) throws SQLException { + return null; + } + + @Override + public Time getTime(int columnIndex, Calendar cal) throws SQLException { + return null; + } + + @Override + public Time getTime(String columnLabel, Calendar cal) throws SQLException { + return null; + } + + @Override + public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException { + return null; + } + + @Override + public Timestamp getTimestamp(String columnLabel, Calendar cal) throws SQLException { + return null; + } + + @Override + public URL getURL(int columnIndex) throws SQLException { + return null; + } + + @Override + public URL getURL(String columnLabel) throws SQLException { + return null; + } + + @Override + public void updateRef(int columnIndex, Ref x) throws SQLException { + + } + + @Override + public void updateRef(String columnLabel, Ref x) throws SQLException { + + } + + @Override + public void updateBlob(int columnIndex, Blob x) throws SQLException { + + } + + @Override + public void updateBlob(String columnLabel, Blob x) throws SQLException { + + } + + @Override + public void updateClob(int columnIndex, Clob x) throws SQLException { + + } + + @Override + public void updateClob(String columnLabel, Clob x) throws SQLException { + + } + + @Override + public void updateArray(int columnIndex, Array x) throws SQLException { + + } + + @Override + public void updateArray(String columnLabel, Array x) throws SQLException { + + } + + @Override + public RowId getRowId(int columnIndex) throws SQLException { + return null; + } + + @Override + public RowId getRowId(String columnLabel) throws SQLException { + return null; + } + + @Override + public void updateRowId(int columnIndex, RowId x) throws SQLException { + + } + + @Override + public void updateRowId(String columnLabel, RowId x) throws SQLException { + + } + + @Override + public int getHoldability() throws SQLException { + return 0; + } + + @Override + public boolean isClosed() throws SQLException { + return false; + } + + @Override + public void updateNString(int columnIndex, String nString) throws SQLException { + + } + + @Override + public void updateNString(String columnLabel, String nString) throws SQLException { + + } + + @Override + public void updateNClob(int columnIndex, NClob nClob) throws SQLException { + + } + + @Override + public void updateNClob(String columnLabel, NClob nClob) throws SQLException { + + } + + @Override + public NClob getNClob(int columnIndex) throws SQLException { + return null; + } + + @Override + public NClob getNClob(String columnLabel) throws SQLException { + return null; + } + + @Override + public SQLXML getSQLXML(int columnIndex) throws SQLException { + return null; + } + + @Override + public SQLXML getSQLXML(String columnLabel) throws SQLException { + return null; + } + + @Override + public void updateSQLXML(int columnIndex, SQLXML xmlObject) throws SQLException { + + } + + @Override + public void updateSQLXML(String columnLabel, SQLXML xmlObject) throws SQLException { + + } + + @Override + public String getNString(int columnIndex) throws SQLException { + return ""; + } + + @Override + public String getNString(String columnLabel) throws SQLException { + return ""; + } + + @Override + public Reader getNCharacterStream(int columnIndex) throws SQLException { + return null; + } + + @Override + public Reader getNCharacterStream(String columnLabel) throws SQLException { + return null; + } + + @Override + public void updateNCharacterStream(int columnIndex, Reader x, long length) throws SQLException { + + } + + @Override + public void updateNCharacterStream(String columnLabel, Reader reader, long length) throws SQLException { + + } + + @Override + public void updateAsciiStream(int columnIndex, InputStream x, long length) throws SQLException { + + } + + @Override + public void updateBinaryStream(int columnIndex, InputStream x, long length) throws SQLException { + + } + + @Override + public void updateCharacterStream(int columnIndex, Reader x, long length) throws SQLException { + + } + + @Override + public void updateAsciiStream(String columnLabel, InputStream x, long length) throws SQLException { + + } + + @Override + public void updateBinaryStream(String columnLabel, InputStream x, long length) throws SQLException { + + } + + @Override + public void updateCharacterStream(String columnLabel, Reader reader, long length) throws SQLException { + + } + + @Override + public void updateBlob(int columnIndex, InputStream inputStream, long length) throws SQLException { + + } + + @Override + public void updateBlob(String columnLabel, InputStream inputStream, long length) throws SQLException { + + } + + @Override + public void updateClob(int columnIndex, Reader reader, long length) throws SQLException { + + } + + @Override + public void updateClob(String columnLabel, Reader reader, long length) throws SQLException { + + } + + @Override + public void updateNClob(int columnIndex, Reader reader, long length) throws SQLException { + + } + + @Override + public void updateNClob(String columnLabel, Reader reader, long length) throws SQLException { + + } + + @Override + public void updateNCharacterStream(int columnIndex, Reader x) throws SQLException { + + } + + @Override + public void updateNCharacterStream(String columnLabel, Reader reader) throws SQLException { + + } + + @Override + public void updateAsciiStream(int columnIndex, InputStream x) throws SQLException { + + } + + @Override + public void updateBinaryStream(int columnIndex, InputStream x) throws SQLException { + + } + + @Override + public void updateCharacterStream(int columnIndex, Reader x) throws SQLException { + + } + + @Override + public void updateAsciiStream(String columnLabel, InputStream x) throws SQLException { + + } + + @Override + public void updateBinaryStream(String columnLabel, InputStream x) throws SQLException { + + } + + @Override + public void updateCharacterStream(String columnLabel, Reader reader) throws SQLException { + + } + + @Override + public void updateBlob(int columnIndex, InputStream inputStream) throws SQLException { + + } + + @Override + public void updateBlob(String columnLabel, InputStream inputStream) throws SQLException { + + } + + @Override + public void updateClob(int columnIndex, Reader reader) throws SQLException { + + } + + @Override + public void updateClob(String columnLabel, Reader reader) throws SQLException { + + } + + @Override + public void updateNClob(int columnIndex, Reader reader) throws SQLException { + + } + + @Override + public void updateNClob(String columnLabel, Reader reader) throws SQLException { + + } + + @Override + public T getObject(int columnIndex, Class type) throws SQLException { + return null; + } + + @Override + public T getObject(String columnLabel, Class type) throws SQLException { + return null; + } + + @Override + public T unwrap(Class iface) throws SQLException { + return null; + } + + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + return false; + } +} diff --git a/persistence/src/test/java/com/alibaba/nacos/persistence/datasource/mock/MockStatement.java b/persistence/src/test/java/com/alibaba/nacos/persistence/datasource/mock/MockStatement.java new file mode 100644 index 00000000000..7a0c8959b5c --- /dev/null +++ b/persistence/src/test/java/com/alibaba/nacos/persistence/datasource/mock/MockStatement.java @@ -0,0 +1,246 @@ +/* + * Copyright 1999-2023 Alibaba Group Holding Ltd. + * + * Licensed 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 com.alibaba.nacos.persistence.datasource.mock; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.SQLWarning; +import java.sql.Statement; + +public class MockStatement implements Statement { + + @Override + public ResultSet executeQuery(String sql) throws SQLException { + return new MockResultSet(); + } + + @Override + public void close() throws SQLException { + + } + + @Override + public int getMaxFieldSize() throws SQLException { + return 0; + } + + @Override + public void setMaxFieldSize(int max) throws SQLException { + + } + + @Override + public int getMaxRows() throws SQLException { + return 0; + } + + @Override + public void setMaxRows(int max) throws SQLException { + + } + + @Override + public void setEscapeProcessing(boolean enable) throws SQLException { + + } + + @Override + public int getQueryTimeout() throws SQLException { + return 0; + } + + @Override + public void setQueryTimeout(int seconds) throws SQLException { + + } + + @Override + public void cancel() throws SQLException { + + } + + @Override + public SQLWarning getWarnings() throws SQLException { + return null; + } + + @Override + public void clearWarnings() throws SQLException { + + } + + @Override + public void setCursorName(String name) throws SQLException { + + } + + @Override + public ResultSet getResultSet() throws SQLException { + return new MockResultSet(); + } + + @Override + public int getUpdateCount() throws SQLException { + return 0; + } + + @Override + public boolean getMoreResults() throws SQLException { + return false; + } + + @Override + public boolean getMoreResults(int current) throws SQLException { + return false; + } + + @Override + public void setFetchDirection(int direction) throws SQLException { + + } + + @Override + public int getFetchDirection() throws SQLException { + return 0; + } + + @Override + public void setFetchSize(int rows) throws SQLException { + + } + + @Override + public int getFetchSize() throws SQLException { + return 0; + } + + @Override + public int getResultSetConcurrency() throws SQLException { + return 0; + } + + @Override + public int getResultSetType() throws SQLException { + return 0; + } + + @Override + public void addBatch(String sql) throws SQLException { + + } + + @Override + public void clearBatch() throws SQLException { + + } + + @Override + public int[] executeBatch() throws SQLException { + return new int[0]; + } + + @Override + public Connection getConnection() throws SQLException { + return null; + } + + @Override + public ResultSet getGeneratedKeys() throws SQLException { + return new MockResultSet(); + } + + @Override + public int executeUpdate(String sql) throws SQLException { + return 0; + } + + @Override + public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException { + return 0; + } + + @Override + public int executeUpdate(String sql, int[] columnIndexes) throws SQLException { + return 0; + } + + @Override + public int executeUpdate(String sql, String[] columnNames) throws SQLException { + return 0; + } + + @Override + public boolean execute(String sql) throws SQLException { + return false; + } + + @Override + public boolean execute(String sql, int autoGeneratedKeys) throws SQLException { + return false; + } + + @Override + public boolean execute(String sql, int[] columnIndexes) throws SQLException { + return false; + } + + @Override + public boolean execute(String sql, String[] columnNames) throws SQLException { + return false; + } + + @Override + public int getResultSetHoldability() throws SQLException { + return 0; + } + + @Override + public boolean isClosed() throws SQLException { + return false; + } + + @Override + public void setPoolable(boolean poolable) throws SQLException { + + } + + @Override + public boolean isPoolable() throws SQLException { + return false; + } + + @Override + public void closeOnCompletion() throws SQLException { + + } + + @Override + public boolean isCloseOnCompletion() throws SQLException { + return false; + } + + @Override + public T unwrap(Class iface) throws SQLException { + return null; + } + + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + return false; + } +} diff --git a/persistence/src/test/java/com/alibaba/nacos/persistence/exception/NJdbcExceptionTest.java b/persistence/src/test/java/com/alibaba/nacos/persistence/exception/NJdbcExceptionTest.java new file mode 100644 index 00000000000..0b2fd9ebdf9 --- /dev/null +++ b/persistence/src/test/java/com/alibaba/nacos/persistence/exception/NJdbcExceptionTest.java @@ -0,0 +1,79 @@ +/* + * Copyright 1999-2023 Alibaba Group Holding Ltd. + * + * Licensed 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 com.alibaba.nacos.persistence.exception; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertSame; + +class NJdbcExceptionTest { + + private Throwable cause; + + @BeforeEach + public void setUp() { + cause = new IllegalStateException("IllegalStateException"); + } + + @Test + public void tesConstructorWithMessage() { + String msg = "test msg"; + NJdbcException exception = new NJdbcException(msg); + assertEquals(msg, exception.getMessage()); + assertNull(exception.getCause()); + assertNull(exception.getOriginExceptionName()); + } + + @Test + public void testConstructorWithMessageAndOriginExceptionName() { + String msg = "test msg"; + String originExceptionName = "OriginException"; + NJdbcException exception = new NJdbcException(msg, originExceptionName); + assertEquals(msg, exception.getMessage()); + assertEquals(originExceptionName, exception.getOriginExceptionName()); + } + + @Test + public void testConstructorWithMessageCauseAndOriginExceptionName() { + String msg = "test msg"; + String originExceptionName = "OriginException"; + NJdbcException exception = new NJdbcException(msg, cause, originExceptionName); + assertEquals("test msg; nested exception is java.lang.IllegalStateException: IllegalStateException", exception.getMessage()); + assertSame(cause, exception.getCause()); + assertEquals(originExceptionName, exception.getOriginExceptionName()); + } + + @Test + public void testConstructorWithMessageAndCause() { + String msg = "test msg"; + NJdbcException exception = new NJdbcException(msg, cause); + assertEquals("test msg; nested exception is java.lang.IllegalStateException: IllegalStateException", exception.getMessage()); + assertSame(cause, exception.getCause()); + assertNull(exception.getOriginExceptionName()); + } + + @Test + public void testConstructorWithCause() { + NJdbcException exception = new NJdbcException(cause); + assertEquals("; nested exception is java.lang.IllegalStateException: IllegalStateException", exception.getMessage()); + assertSame(cause, exception.getCause()); + assertNull(exception.getOriginExceptionName()); + } +} \ No newline at end of file diff --git a/persistence/src/test/java/com/alibaba/nacos/persistence/model/PageTest.java b/persistence/src/test/java/com/alibaba/nacos/persistence/model/PageTest.java new file mode 100644 index 00000000000..fb5900026e0 --- /dev/null +++ b/persistence/src/test/java/com/alibaba/nacos/persistence/model/PageTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 1999-2023 Alibaba Group Holding Ltd. + * + * Licensed 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 com.alibaba.nacos.persistence.model; + +import org.junit.jupiter.api.Test; + +import java.util.Collections; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class PageTest { + + @Test + void setPageItems() { + Page page = new Page<>(); + assertEquals(0, page.getPageItems().size()); + page.setPageItems(Collections.singletonList(new Object())); + assertEquals(1, page.getPageItems().size()); + } +} \ No newline at end of file diff --git a/persistence/src/test/java/com/alibaba/nacos/persistence/model/event/EventTest.java b/persistence/src/test/java/com/alibaba/nacos/persistence/model/event/EventTest.java new file mode 100644 index 00000000000..13d817a2c67 --- /dev/null +++ b/persistence/src/test/java/com/alibaba/nacos/persistence/model/event/EventTest.java @@ -0,0 +1,48 @@ +/* + * Copyright 1999-2023 Alibaba Group Holding Ltd. + * + * Licensed 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 com.alibaba.nacos.persistence.model.event; + +import com.alibaba.nacos.common.utils.JacksonUtils; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class EventTest { + + @Test + void testDerbyImportEvent() { + DerbyImportEvent event = new DerbyImportEvent(true); + assertTrue(event.isFinished()); + } + + @Test + void testDerbyLoadEvent() { + DerbyLoadEvent event = DerbyLoadEvent.INSTANCE; + assertNotNull(event); + } + + @Test + void testRaftDbErrorEvent() { + RaftDbErrorEvent event = new RaftDbErrorEvent(new Exception("test")); + assertNotNull(event); + String json = JacksonUtils.toJson(event); + RaftDbErrorEvent deserialized = JacksonUtils.toObj(json, RaftDbErrorEvent.class); + assertInstanceOf(Throwable.class, deserialized.getEx()); + } +} \ No newline at end of file diff --git a/persistence/src/test/java/com/alibaba/nacos/persistence/repository/RowMapperManagerTest.java b/persistence/src/test/java/com/alibaba/nacos/persistence/repository/RowMapperManagerTest.java new file mode 100644 index 00000000000..2ec50ca8300 --- /dev/null +++ b/persistence/src/test/java/com/alibaba/nacos/persistence/repository/RowMapperManagerTest.java @@ -0,0 +1,89 @@ +/* + * Copyright 1999-2023 Alibaba Group Holding Ltd. + * + * Licensed 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 com.alibaba.nacos.persistence.repository; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.jdbc.core.RowMapper; + +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class RowMapperManagerTest { + + @Mock + ResultSet resultSet; + + @Mock + ResultSetMetaData resultSetMetaData; + + @BeforeEach + void setUp() throws SQLException { + } + + @AfterEach + void tearDown() { + RowMapperManager.mapperMap.clear(); + RowMapperManager.registerRowMapper(RowMapperManager.MAP_ROW_MAPPER.getClass().getCanonicalName(), + RowMapperManager.MAP_ROW_MAPPER); + } + + @Test + void testRegisterRowMapper() { + MockMapRowMapper mapper1 = new MockMapRowMapper(); + RowMapperManager.registerRowMapper(MockMapRowMapperObj.class.getCanonicalName(), mapper1); + assertEquals(mapper1, RowMapperManager.getRowMapper(MockMapRowMapperObj.class.getCanonicalName())); + MockMapRowMapper mapper2 = new MockMapRowMapper(); + RowMapperManager.registerRowMapper(MockMapRowMapperObj.class.getCanonicalName(), mapper2); + assertEquals(mapper2, RowMapperManager.getRowMapper(MockMapRowMapperObj.class.getCanonicalName())); + } + + @Test + void testDefaultRowMapper() throws SQLException { + when(resultSet.getObject(1)).thenReturn(1L); + when(resultSet.getObject(2)).thenReturn("test"); + when(resultSet.getMetaData()).thenReturn(resultSetMetaData); + when(resultSetMetaData.getColumnCount()).thenReturn(2); + when(resultSetMetaData.getColumnLabel(1)).thenReturn("id"); + when(resultSetMetaData.getColumnLabel(2)).thenReturn("name"); + Map actual = RowMapperManager.MAP_ROW_MAPPER.mapRow(resultSet, 1); + assertEquals(1L, actual.get("id")); + assertEquals("test", actual.get("name")); + } + + private static class MockMapRowMapper implements RowMapper { + + @Override + public MockMapRowMapperObj mapRow(ResultSet rs, int rowNum) throws SQLException { + return new MockMapRowMapperObj(); + } + } + + private static class MockMapRowMapperObj { + + } +} \ No newline at end of file diff --git a/persistence/src/test/java/com/alibaba/nacos/persistence/repository/embedded/EmbeddedPaginationHelperImplTest.java b/persistence/src/test/java/com/alibaba/nacos/persistence/repository/embedded/EmbeddedPaginationHelperImplTest.java new file mode 100644 index 00000000000..22c64c9d223 --- /dev/null +++ b/persistence/src/test/java/com/alibaba/nacos/persistence/repository/embedded/EmbeddedPaginationHelperImplTest.java @@ -0,0 +1,350 @@ +/* + * Copyright 1999-2023 Alibaba Group Holding Ltd. + * + * Licensed 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 com.alibaba.nacos.persistence.repository.embedded; + +import com.alibaba.nacos.persistence.model.Page; +import com.alibaba.nacos.persistence.repository.embedded.operate.DatabaseOperate; +import com.alibaba.nacos.plugin.datasource.model.MapperResult; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.jdbc.core.RowMapper; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class EmbeddedPaginationHelperImplTest { + + private static final String QUERY_SQL = "SELECT * FROM config_info LIMIT 1"; + + private static final String QUERY_COUNT_SQL = "SELECT count(*) FROM config_info"; + + @Mock + DatabaseOperate databaseOperate; + + @Mock + RowMapper rowMapper; + + EmbeddedPaginationHelperImpl embeddedPaginationHelper; + + @BeforeEach + void setUp() { + embeddedPaginationHelper = new EmbeddedPaginationHelperImpl<>(databaseOperate); + } + + @AfterEach + void tearDown() { + } + + @Test + void testFetchPageWithIllegalPageInfo() { + assertThrows(IllegalArgumentException.class, + () -> embeddedPaginationHelper.fetchPage("", "", new Object[] {}, 0, 0, null)); + assertThrows(IllegalArgumentException.class, + () -> embeddedPaginationHelper.fetchPage("", "", new Object[] {}, 1, 0, null)); + } + + @Test + void testFetchPageWithoutResult() { + when(databaseOperate.queryOne(QUERY_COUNT_SQL, new Object[] {}, Integer.class)).thenReturn(null); + assertThrows(IllegalArgumentException.class, + () -> embeddedPaginationHelper.fetchPage(QUERY_COUNT_SQL, QUERY_SQL, new Object[] {}, 1, 1, null)); + } + + @Test + void testFetchPageOnePage() { + when(databaseOperate.queryOne(QUERY_COUNT_SQL, new Object[] {}, Integer.class)).thenReturn(1); + when(databaseOperate.queryMany(QUERY_SQL, new Object[] {}, rowMapper)).thenReturn( + Collections.singletonList(new Object())); + Page actual = embeddedPaginationHelper.fetchPage(QUERY_COUNT_SQL, QUERY_SQL, new Object[] {}, 1, 1, + rowMapper); + assertEquals(1, actual.getTotalCount()); + assertEquals(1, actual.getPageNumber()); + assertEquals(1, actual.getPagesAvailable()); + assertEquals(1, actual.getPageItems().size()); + } + + @Test + void testFetchPageMorePageFull() { + when(databaseOperate.queryOne(QUERY_COUNT_SQL, new Object[] {}, Integer.class)).thenReturn(2); + when(databaseOperate.queryMany(QUERY_SQL, new Object[] {}, rowMapper)).thenReturn( + Collections.singletonList(new Object())); + Page actual = embeddedPaginationHelper.fetchPage(QUERY_COUNT_SQL, QUERY_SQL, new Object[] {}, 1, 1, + rowMapper); + assertEquals(2, actual.getTotalCount()); + assertEquals(1, actual.getPageNumber()); + assertEquals(2, actual.getPagesAvailable()); + assertEquals(1, actual.getPageItems().size()); + } + + @Test + void testFetchPageMorePageNotFull() { + when(databaseOperate.queryOne(QUERY_COUNT_SQL, new Object[] {}, Integer.class)).thenReturn(3); + List pageItems = new LinkedList<>(); + pageItems.add(new Object()); + pageItems.add(new Object()); + when(databaseOperate.queryMany(QUERY_SQL, new Object[] {}, rowMapper)).thenReturn(pageItems); + Page actual = embeddedPaginationHelper.fetchPage(QUERY_COUNT_SQL, QUERY_SQL, new Object[] {}, 1, 2, + rowMapper); + assertEquals(3, actual.getTotalCount()); + assertEquals(1, actual.getPageNumber()); + assertEquals(2, actual.getPagesAvailable()); + assertEquals(2, actual.getPageItems().size()); + } + + @Test + void testFetchPageMorePageNextPage() { + when(databaseOperate.queryOne(QUERY_COUNT_SQL, new Object[] {}, Integer.class)).thenReturn(3); + when(databaseOperate.queryMany(QUERY_SQL, new Object[] {}, rowMapper)).thenReturn( + Collections.singletonList(new Object())); + Page actual = embeddedPaginationHelper.fetchPage(QUERY_COUNT_SQL, QUERY_SQL, new Object[] {}, 2, 2, + rowMapper); + assertEquals(3, actual.getTotalCount()); + assertEquals(2, actual.getPageNumber()); + assertEquals(2, actual.getPagesAvailable()); + assertEquals(1, actual.getPageItems().size()); + } + + @Test + void testFetchPageMoreThanItemCount() { + when(databaseOperate.queryOne(QUERY_COUNT_SQL, new Object[] {}, Integer.class)).thenReturn(3); + Page actual = embeddedPaginationHelper.fetchPage(QUERY_COUNT_SQL, QUERY_SQL, new Object[] {}, 3, 2, + rowMapper); + assertEquals(3, actual.getTotalCount()); + assertEquals(3, actual.getPageNumber()); + assertEquals(2, actual.getPagesAvailable()); + assertEquals(0, actual.getPageItems().size()); + } + + @Test + void testFetchPageLimitWithIllegalPageInfo() { + assertThrows(IllegalArgumentException.class, + () -> embeddedPaginationHelper.fetchPageLimit("", "", new Object[] {}, 0, 0, null)); + assertThrows(IllegalArgumentException.class, + () -> embeddedPaginationHelper.fetchPageLimit("", "", new Object[] {}, 1, 0, null)); + } + + @Test + void testFetchPageLimitWithoutResult() { + when(databaseOperate.queryOne(QUERY_COUNT_SQL, Integer.class)).thenReturn(null); + assertThrows(IllegalArgumentException.class, + () -> embeddedPaginationHelper.fetchPageLimit(QUERY_COUNT_SQL, QUERY_SQL, new Object[] {}, 1, 1, null)); + } + + @Test + void testFetchPageLimitOnePage() { + when(databaseOperate.queryOne(QUERY_COUNT_SQL, Integer.class)).thenReturn(1); + when(databaseOperate.queryMany(QUERY_SQL, new Object[] {}, rowMapper)).thenReturn( + Collections.singletonList(new Object())); + Page actual = embeddedPaginationHelper.fetchPageLimit(QUERY_COUNT_SQL, QUERY_SQL, new Object[] {}, 1, 1, + rowMapper); + assertEquals(1, actual.getTotalCount()); + assertEquals(1, actual.getPageNumber()); + assertEquals(1, actual.getPagesAvailable()); + assertEquals(1, actual.getPageItems().size()); + } + + @Test + void testFetchPageLimitMorePageFull() { + when(databaseOperate.queryOne(QUERY_COUNT_SQL, Integer.class)).thenReturn(2); + when(databaseOperate.queryMany(QUERY_SQL, new Object[] {}, rowMapper)).thenReturn( + Collections.singletonList(new Object())); + Page actual = embeddedPaginationHelper.fetchPageLimit(QUERY_COUNT_SQL, QUERY_SQL, new Object[] {}, 1, 1, + rowMapper); + assertEquals(2, actual.getTotalCount()); + assertEquals(1, actual.getPageNumber()); + assertEquals(2, actual.getPagesAvailable()); + assertEquals(1, actual.getPageItems().size()); + } + + @Test + void testFetchPageLimitMorePageNotFull() { + when(databaseOperate.queryOne(QUERY_COUNT_SQL, Integer.class)).thenReturn(3); + List pageItems = new LinkedList<>(); + pageItems.add(new Object()); + pageItems.add(new Object()); + when(databaseOperate.queryMany(QUERY_SQL, new Object[] {}, rowMapper)).thenReturn(pageItems); + Page actual = embeddedPaginationHelper.fetchPageLimit(QUERY_COUNT_SQL, QUERY_SQL, new Object[] {}, 1, 2, + rowMapper); + assertEquals(3, actual.getTotalCount()); + assertEquals(1, actual.getPageNumber()); + assertEquals(2, actual.getPagesAvailable()); + assertEquals(2, actual.getPageItems().size()); + } + + @Test + void testFetchPageLimitMorePageNextPage() { + when(databaseOperate.queryOne(QUERY_COUNT_SQL, Integer.class)).thenReturn(3); + when(databaseOperate.queryMany(QUERY_SQL, new Object[] {}, rowMapper)).thenReturn( + Collections.singletonList(new Object())); + Page actual = embeddedPaginationHelper.fetchPageLimit(QUERY_COUNT_SQL, QUERY_SQL, new Object[] {}, 2, 2, + rowMapper); + assertEquals(3, actual.getTotalCount()); + assertEquals(2, actual.getPageNumber()); + assertEquals(2, actual.getPagesAvailable()); + assertEquals(1, actual.getPageItems().size()); + } + + @Test + void testFetchPageLimitMoreThanItemCount() { + when(databaseOperate.queryOne(QUERY_COUNT_SQL, Integer.class)).thenReturn(3); + Page actual = embeddedPaginationHelper.fetchPageLimit(QUERY_COUNT_SQL, QUERY_SQL, new Object[] {}, 3, 2, + rowMapper); + assertEquals(3, actual.getTotalCount()); + assertEquals(3, actual.getPageNumber()); + assertEquals(2, actual.getPagesAvailable()); + assertEquals(0, actual.getPageItems().size()); + } + + @Test + void testFetchPageLimitWithPluginWithIllegalPageInfo() { + MapperResult countMapper = new MapperResult(QUERY_COUNT_SQL, new ArrayList<>()); + MapperResult queryMapper = new MapperResult(QUERY_SQL, new ArrayList<>()); + assertThrows(IllegalArgumentException.class, + () -> embeddedPaginationHelper.fetchPageLimit(countMapper, queryMapper, 0, 0, null)); + assertThrows(IllegalArgumentException.class, + () -> embeddedPaginationHelper.fetchPageLimit(countMapper, queryMapper, 1, 0, null)); + } + + @Test + void testFetchPageLimitWithPluginWithoutResult() { + MapperResult countMapper = new MapperResult(QUERY_COUNT_SQL, new ArrayList<>()); + MapperResult queryMapper = new MapperResult(QUERY_SQL, new ArrayList<>()); + when(databaseOperate.queryOne(QUERY_COUNT_SQL, new Object[] {}, Integer.class)).thenReturn(null); + assertThrows(IllegalArgumentException.class, + () -> embeddedPaginationHelper.fetchPageLimit(countMapper, queryMapper, 1, 1, null)); + } + + @Test + void testFetchPageLimitWithPluginPageOnePage() { + MapperResult countMapper = new MapperResult(QUERY_COUNT_SQL, new ArrayList<>()); + MapperResult queryMapper = new MapperResult(QUERY_SQL, new ArrayList<>()); + when(databaseOperate.queryOne(QUERY_COUNT_SQL, new Object[] {}, Integer.class)).thenReturn(1); + when(databaseOperate.queryMany(QUERY_SQL, new Object[] {}, rowMapper)).thenReturn( + Collections.singletonList(new Object())); + Page actual = embeddedPaginationHelper.fetchPageLimit(countMapper, queryMapper, 1, 1, rowMapper); + assertEquals(1, actual.getTotalCount()); + assertEquals(1, actual.getPageNumber()); + assertEquals(1, actual.getPagesAvailable()); + assertEquals(1, actual.getPageItems().size()); + } + + @Test + void testFetchPageLimitWithPluginMorePageFull() { + MapperResult countMapper = new MapperResult(QUERY_COUNT_SQL, new ArrayList<>()); + MapperResult queryMapper = new MapperResult(QUERY_SQL, new ArrayList<>()); + when(databaseOperate.queryOne(QUERY_COUNT_SQL, new Object[] {}, Integer.class)).thenReturn(2); + when(databaseOperate.queryMany(QUERY_SQL, new Object[] {}, rowMapper)).thenReturn( + Collections.singletonList(new Object())); + Page actual = embeddedPaginationHelper.fetchPageLimit(countMapper, queryMapper, 1, 1, rowMapper); + assertEquals(2, actual.getTotalCount()); + assertEquals(1, actual.getPageNumber()); + assertEquals(2, actual.getPagesAvailable()); + assertEquals(1, actual.getPageItems().size()); + } + + @Test + void testFetchPageLimitWithPluginMorePageNotFull() { + when(databaseOperate.queryOne(QUERY_COUNT_SQL, new Object[] {}, Integer.class)).thenReturn(3); + List pageItems = new LinkedList<>(); + pageItems.add(new Object()); + pageItems.add(new Object()); + MapperResult countMapper = new MapperResult(QUERY_COUNT_SQL, new ArrayList<>()); + MapperResult queryMapper = new MapperResult(QUERY_SQL, new ArrayList<>()); + when(databaseOperate.queryMany(QUERY_SQL, new Object[] {}, rowMapper)).thenReturn(pageItems); + Page actual = embeddedPaginationHelper.fetchPageLimit(countMapper, queryMapper, 1, 2, rowMapper); + assertEquals(3, actual.getTotalCount()); + assertEquals(1, actual.getPageNumber()); + assertEquals(2, actual.getPagesAvailable()); + assertEquals(2, actual.getPageItems().size()); + } + + @Test + void testFetchPageLimitWithPluginMorePageNextPage() { + MapperResult countMapper = new MapperResult(QUERY_COUNT_SQL, new ArrayList<>()); + MapperResult queryMapper = new MapperResult(QUERY_SQL, new ArrayList<>()); + when(databaseOperate.queryOne(QUERY_COUNT_SQL, new Object[] {}, Integer.class)).thenReturn(3); + when(databaseOperate.queryMany(QUERY_SQL, new Object[] {}, rowMapper)).thenReturn( + Collections.singletonList(new Object())); + Page actual = embeddedPaginationHelper.fetchPageLimit(countMapper, queryMapper, 2, 2, rowMapper); + assertEquals(3, actual.getTotalCount()); + assertEquals(2, actual.getPageNumber()); + assertEquals(2, actual.getPagesAvailable()); + assertEquals(1, actual.getPageItems().size()); + } + + @Test + void testFetchPageLimitWithPluginMoreThanItemCount() { + MapperResult countMapper = new MapperResult(QUERY_COUNT_SQL, new ArrayList<>()); + MapperResult queryMapper = new MapperResult(QUERY_SQL, new ArrayList<>()); + when(databaseOperate.queryOne(QUERY_COUNT_SQL, new Object[] {}, Integer.class)).thenReturn(3); + Page actual = embeddedPaginationHelper.fetchPageLimit(countMapper, queryMapper, 3, 2, rowMapper); + assertEquals(3, actual.getTotalCount()); + assertEquals(3, actual.getPageNumber()); + assertEquals(2, actual.getPagesAvailable()); + assertEquals(0, actual.getPageItems().size()); + } + + @Test + void testFetchPageLimitSimpleWithIllegalPageInfo() { + assertThrows(IllegalArgumentException.class, + () -> embeddedPaginationHelper.fetchPageLimit(QUERY_SQL, new Object[] {}, 0, 0, null)); + assertThrows(IllegalArgumentException.class, + () -> embeddedPaginationHelper.fetchPageLimit(QUERY_SQL, new Object[] {}, 1, 0, null)); + } + + @Test + void testFetchPageLimitSimpleWithData() { + List pageItems = new LinkedList<>(); + pageItems.add(new Object()); + pageItems.add(new Object()); + pageItems.add(new Object()); + when(databaseOperate.queryMany(QUERY_SQL, new Object[] {}, rowMapper)).thenReturn(pageItems); + Page actual = embeddedPaginationHelper.fetchPageLimit(QUERY_SQL, new Object[] {}, 3, 1, rowMapper); + assertEquals(0, actual.getTotalCount()); + assertEquals(0, actual.getPageNumber()); + assertEquals(0, actual.getPagesAvailable()); + assertEquals(3, actual.getPageItems().size()); + } + + @Test + void updateLimit() { + Object[] args = new Object[] {}; + embeddedPaginationHelper.updateLimit(QUERY_SQL, args); + verify(databaseOperate).update(argThat(modifyRequests -> { + if (modifyRequests.size() != 1) { + return false; + } + if (!QUERY_SQL.equals(modifyRequests.get(0).getSql())) { + return false; + } + return 0 == modifyRequests.get(0).getArgs().length; + })); + } +} \ No newline at end of file diff --git a/persistence/src/test/java/com/alibaba/nacos/persistence/repository/embedded/EmbeddedStorageContextHolderTest.java b/persistence/src/test/java/com/alibaba/nacos/persistence/repository/embedded/EmbeddedStorageContextHolderTest.java new file mode 100644 index 00000000000..2774a6f72a2 --- /dev/null +++ b/persistence/src/test/java/com/alibaba/nacos/persistence/repository/embedded/EmbeddedStorageContextHolderTest.java @@ -0,0 +1,70 @@ +/* + * Copyright 1999-2023 Alibaba Group Holding Ltd. + * + * Licensed 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 com.alibaba.nacos.persistence.repository.embedded; + +import com.alibaba.nacos.persistence.repository.embedded.sql.ModifyRequest; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class EmbeddedStorageContextHolderTest { + + private static final String TEST_SQL = "SELECT * FROM config_info"; + + @BeforeEach + void setUp() { + } + + @AfterEach + void tearDown() { + EmbeddedStorageContextHolder.cleanAllContext(); + } + + @Test + void testAddSqlContextRollbackOnUpdateFail() { + EmbeddedStorageContextHolder.addSqlContext(true, TEST_SQL, "test"); + List requests = EmbeddedStorageContextHolder.getCurrentSqlContext(); + assertEquals(1, requests.size()); + assertEquals(TEST_SQL, requests.get(0).getSql()); + assertEquals(0, requests.get(0).getExecuteNo()); + assertEquals("test", requests.get(0).getArgs()[0]); + assertTrue(requests.get(0).isRollBackOnUpdateFail()); + } + + @Test + void testPutExtendInfo() { + EmbeddedStorageContextHolder.putExtendInfo("testPutExtendInfo", "test_value"); + assertTrue(EmbeddedStorageContextHolder.containsExtendInfo("testPutExtendInfo")); + assertEquals("test_value", EmbeddedStorageContextHolder.getCurrentExtendInfo().get("testPutExtendInfo")); + } + + @Test + void testPutAllExtendInfo() { + Map map = new HashMap<>(); + map.put("testPutAllExtendInfo", "test_value"); + EmbeddedStorageContextHolder.putAllExtendInfo(map); + assertTrue(EmbeddedStorageContextHolder.containsExtendInfo("testPutAllExtendInfo")); + assertEquals("test_value", EmbeddedStorageContextHolder.getCurrentExtendInfo().get("testPutAllExtendInfo")); + } +} \ No newline at end of file diff --git a/persistence/src/test/java/com/alibaba/nacos/persistence/repository/embedded/hook/EmbeddedApplyHookHolderTest.java b/persistence/src/test/java/com/alibaba/nacos/persistence/repository/embedded/hook/EmbeddedApplyHookHolderTest.java new file mode 100644 index 00000000000..8e26d170fe9 --- /dev/null +++ b/persistence/src/test/java/com/alibaba/nacos/persistence/repository/embedded/hook/EmbeddedApplyHookHolderTest.java @@ -0,0 +1,57 @@ +/* + * Copyright 1999-2023 Alibaba Group Holding Ltd. + * + * Licensed 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 com.alibaba.nacos.persistence.repository.embedded.hook; + +import com.alibaba.nacos.consistency.entity.WriteRequest; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.HashSet; +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class EmbeddedApplyHookHolderTest { + + Set cached; + + @BeforeEach + void setUp() { + cached = new HashSet<>(EmbeddedApplyHookHolder.getInstance().getAllHooks()); + EmbeddedApplyHookHolder.getInstance().getAllHooks().clear(); + } + + @AfterEach + void tearDown() { + EmbeddedApplyHookHolder.getInstance().getAllHooks().clear(); + EmbeddedApplyHookHolder.getInstance().getAllHooks().addAll(cached); + } + + @Test + void testRegister() { + assertEquals(0, EmbeddedApplyHookHolder.getInstance().getAllHooks().size()); + EmbeddedApplyHook mockHook = new EmbeddedApplyHook() { + @Override + public void afterApply(WriteRequest log) { + + } + }; + assertEquals(1, EmbeddedApplyHookHolder.getInstance().getAllHooks().size()); + assertEquals(mockHook, EmbeddedApplyHookHolder.getInstance().getAllHooks().iterator().next()); + } +} \ No newline at end of file diff --git a/persistence/src/test/java/com/alibaba/nacos/persistence/repository/embedded/operate/BaseDatabaseOperateTest.java b/persistence/src/test/java/com/alibaba/nacos/persistence/repository/embedded/operate/BaseDatabaseOperateTest.java new file mode 100644 index 00000000000..538aed780b3 --- /dev/null +++ b/persistence/src/test/java/com/alibaba/nacos/persistence/repository/embedded/operate/BaseDatabaseOperateTest.java @@ -0,0 +1,205 @@ +/* + * Copyright 1999-2023 Alibaba Group Holding Ltd. + * + * Licensed 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 com.alibaba.nacos.persistence.repository.embedded.operate; + +import com.alibaba.nacos.persistence.exception.NJdbcException; +import com.alibaba.nacos.persistence.repository.embedded.EmbeddedStorageContextHolder; +import com.alibaba.nacos.persistence.repository.embedded.sql.ModifyRequest; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.Spy; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.jdbc.BadSqlGrammarException; +import org.springframework.jdbc.CannotGetJdbcConnectionException; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.transaction.IllegalTransactionStateException; +import org.springframework.transaction.support.SimpleTransactionStatus; +import org.springframework.transaction.support.TransactionCallback; +import org.springframework.transaction.support.TransactionTemplate; + +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import java.util.function.BiConsumer; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class BaseDatabaseOperateTest { + + private static final String TEST_SQL = "UPDATE config_info SET data_id = 'test' WHERE id = ?;"; + + private static final Object[] ARGS = new Object[1]; + + @Spy + BaseDatabaseOperate baseDatabaseOperate; + + @Mock + BiConsumer consumer; + + @Mock + TransactionTemplate transactionTemplate; + + @Mock + JdbcTemplate jdbcTemplate; + + @AfterEach + void tearDown() { + EmbeddedStorageContextHolder.cleanAllContext(); + } + + @Test + void testUpdateSuccessWithConsumer() { + List requests = mockRequest(false); + when(transactionTemplate.execute(any(TransactionCallback.class))).then(invocationOnMock -> { + TransactionCallback callback = invocationOnMock.getArgument(0, TransactionCallback.class); + return callback.doInTransaction(new SimpleTransactionStatus()); + }); + when(jdbcTemplate.update(TEST_SQL, ARGS)).thenReturn(1); + assertTrue(baseDatabaseOperate.update(transactionTemplate, jdbcTemplate, requests, consumer)); + verify(consumer).accept(eq(Boolean.TRUE), eq(null)); + } + + @Test + void testUpdateSuccessWithConsumerAndRollback() { + List requests = mockRequest(true); + when(transactionTemplate.execute(any(TransactionCallback.class))).then(invocationOnMock -> { + TransactionCallback callback = invocationOnMock.getArgument(0, TransactionCallback.class); + return callback.doInTransaction(new SimpleTransactionStatus()); + }); + when(jdbcTemplate.update(TEST_SQL, ARGS)).thenReturn(1); + assertTrue(baseDatabaseOperate.update(transactionTemplate, jdbcTemplate, requests, consumer)); + verify(consumer).accept(eq(Boolean.TRUE), eq(null)); + } + + @Test + void testUpdateFailedWithConsumerAndRollback() { + List requests = mockRequest(true); + when(transactionTemplate.execute(any(TransactionCallback.class))).then(invocationOnMock -> { + TransactionCallback callback = invocationOnMock.getArgument(0, TransactionCallback.class); + return callback.doInTransaction(new SimpleTransactionStatus()); + }); + when(jdbcTemplate.update(TEST_SQL, ARGS)).thenReturn(0); + assertFalse(baseDatabaseOperate.update(transactionTemplate, jdbcTemplate, requests, consumer)); + verify(consumer).accept(eq(Boolean.FALSE), any(IllegalTransactionStateException.class)); + } + + @Test + void testUpdateFailedWithConsumerAndBadSqlException() { + List requests = mockRequest(false); + when(transactionTemplate.execute(any(TransactionCallback.class))).then(invocationOnMock -> { + TransactionCallback callback = invocationOnMock.getArgument(0, TransactionCallback.class); + return callback.doInTransaction(new SimpleTransactionStatus()); + }); + when(jdbcTemplate.update(TEST_SQL, ARGS)).thenThrow( + new BadSqlGrammarException("test", TEST_SQL, new SQLException("test"))); + assertFalse(baseDatabaseOperate.update(transactionTemplate, jdbcTemplate, requests, consumer)); + verify(consumer).accept(eq(Boolean.FALSE), any(BadSqlGrammarException.class)); + } + + @Test + void testUpdateWithConsumerAndBadSqlException() { + List requests = mockRequest(false); + when(transactionTemplate.execute(any(TransactionCallback.class))).then(invocationOnMock -> { + TransactionCallback callback = invocationOnMock.getArgument(0, TransactionCallback.class); + return callback.doInTransaction(new SimpleTransactionStatus()); + }); + when(jdbcTemplate.update(TEST_SQL, ARGS)).thenThrow( + new BadSqlGrammarException("test", TEST_SQL, new SQLException("test"))); + assertFalse(baseDatabaseOperate.update(transactionTemplate, jdbcTemplate, requests, consumer)); + verify(consumer).accept(eq(Boolean.FALSE), any(BadSqlGrammarException.class)); + } + + @Test + void testUpdateWithConsumerAndCannotGetJdbcConnectionException() { + List requests = mockRequest(false); + when(transactionTemplate.execute(any(TransactionCallback.class))).then(invocationOnMock -> { + TransactionCallback callback = invocationOnMock.getArgument(0, TransactionCallback.class); + return callback.doInTransaction(new SimpleTransactionStatus()); + }); + when(jdbcTemplate.update(TEST_SQL, ARGS)).thenThrow(new CannotGetJdbcConnectionException("test")); + assertThrows(CannotGetJdbcConnectionException.class, + () -> baseDatabaseOperate.update(transactionTemplate, jdbcTemplate, requests, consumer)); + verify(consumer, never()).accept(any(), any()); + } + + @Test + void testUpdateWithConsumerAndDataAccessException() { + List requests = mockRequest(false); + when(transactionTemplate.execute(any(TransactionCallback.class))).then(invocationOnMock -> { + TransactionCallback callback = invocationOnMock.getArgument(0, TransactionCallback.class); + return callback.doInTransaction(new SimpleTransactionStatus()); + }); + when(jdbcTemplate.update(TEST_SQL, ARGS)).thenThrow(new NJdbcException("test")); + assertThrows(NJdbcException.class, + () -> baseDatabaseOperate.update(transactionTemplate, jdbcTemplate, requests, consumer)); + verify(consumer, never()).accept(any(), any()); + } + + @Test + void testUpdateSuccessWithoutConsumer() { + List requests = mockRequest(false); + when(transactionTemplate.execute(any(TransactionCallback.class))).then(invocationOnMock -> { + TransactionCallback callback = invocationOnMock.getArgument(0, TransactionCallback.class); + return callback.doInTransaction(new SimpleTransactionStatus()); + }); + when(jdbcTemplate.update(TEST_SQL, ARGS)).thenReturn(1); + assertTrue(baseDatabaseOperate.update(transactionTemplate, jdbcTemplate, requests, null)); + } + + @Test + void testUpdateFailedWithoutConsumerAndRollback() { + List requests = mockRequest(true); + when(transactionTemplate.execute(any(TransactionCallback.class))).then(invocationOnMock -> { + TransactionCallback callback = invocationOnMock.getArgument(0, TransactionCallback.class); + return callback.doInTransaction(new SimpleTransactionStatus()); + }); + when(jdbcTemplate.update(TEST_SQL, ARGS)).thenReturn(0); + assertFalse(baseDatabaseOperate.update(transactionTemplate, jdbcTemplate, requests, null)); + } + + @Test + void testUpdateWithoutConsumerAndDataIntegrityViolationException() { + List requests = mockRequest(false); + when(transactionTemplate.execute(any(TransactionCallback.class))).then(invocationOnMock -> { + TransactionCallback callback = invocationOnMock.getArgument(0, TransactionCallback.class); + return callback.doInTransaction(new SimpleTransactionStatus()); + }); + when(jdbcTemplate.update(TEST_SQL, ARGS)).thenThrow(new DataIntegrityViolationException("test")); + assertFalse(baseDatabaseOperate.update(transactionTemplate, jdbcTemplate, requests, null)); + } + + private List mockRequest(boolean rollback) { + ModifyRequest modifyRequest1 = new ModifyRequest(); + modifyRequest1.setSql(TEST_SQL); + modifyRequest1.setArgs(ARGS); + modifyRequest1.setRollBackOnUpdateFail(rollback); + List modifyRequests = new ArrayList<>(); + modifyRequests.add(modifyRequest1); + return modifyRequests; + } +} \ No newline at end of file diff --git a/persistence/src/test/java/com/alibaba/nacos/persistence/repository/embedded/operate/DatabaseOperateTest.java b/persistence/src/test/java/com/alibaba/nacos/persistence/repository/embedded/operate/DatabaseOperateTest.java new file mode 100644 index 00000000000..05fb706586b --- /dev/null +++ b/persistence/src/test/java/com/alibaba/nacos/persistence/repository/embedded/operate/DatabaseOperateTest.java @@ -0,0 +1,47 @@ +/* + * Copyright 1999-2023 Alibaba Group Holding Ltd. + * + * Licensed 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 com.alibaba.nacos.persistence.repository.embedded.operate; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Spy; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Collections; + +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.anyList; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class DatabaseOperateTest { + + @Spy + private DatabaseOperate databaseOperate; + + @BeforeEach + void setUp() { + } + + @Test + void testDefaultUpdate() { + when(databaseOperate.update(anyList(), eq(null))).thenReturn(true); + assertTrue(databaseOperate.update(Collections.emptyList())); + } +} \ No newline at end of file diff --git a/persistence/src/test/java/com/alibaba/nacos/persistence/repository/embedded/operate/StandaloneDatabaseOperateImplTest.java b/persistence/src/test/java/com/alibaba/nacos/persistence/repository/embedded/operate/StandaloneDatabaseOperateImplTest.java index 6f10f72518f..f2ecbac620f 100644 --- a/persistence/src/test/java/com/alibaba/nacos/persistence/repository/embedded/operate/StandaloneDatabaseOperateImplTest.java +++ b/persistence/src/test/java/com/alibaba/nacos/persistence/repository/embedded/operate/StandaloneDatabaseOperateImplTest.java @@ -17,6 +17,7 @@ package com.alibaba.nacos.persistence.repository.embedded.operate; import com.alibaba.nacos.common.model.RestResult; +import com.alibaba.nacos.persistence.exception.NJdbcException; import com.alibaba.nacos.persistence.repository.embedded.EmbeddedStorageContextHolder; import com.alibaba.nacos.persistence.repository.embedded.sql.ModifyRequest; import com.alibaba.nacos.sys.env.EnvUtil; @@ -25,10 +26,10 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.Spy; import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.dao.IncorrectResultSizeDataAccessException; +import org.springframework.jdbc.CannotGetJdbcConnectionException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; import org.springframework.mock.env.MockEnvironment; @@ -36,27 +37,30 @@ import org.springframework.transaction.support.TransactionCallback; import org.springframework.transaction.support.TransactionTemplate; +import java.io.File; +import java.net.URISyntaxException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.reset; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) class StandaloneDatabaseOperateImplTest { - @Spy - @InjectMocks private StandaloneDatabaseOperateImpl operate; @Mock @@ -71,9 +75,6 @@ class StandaloneDatabaseOperateImplTest { @Mock private BiConsumer biConsumer; - /* @Mock - private File file; - */ @Mock private TransactionTemplate transactionTemplate; @@ -86,6 +87,8 @@ static void beforeAll() { @BeforeEach void setUp() { + operate = new StandaloneDatabaseOperateImpl(); + operate.init(); ReflectionTestUtils.setField(operate, "jdbcTemplate", jdbcTemplate); ReflectionTestUtils.setField(operate, "transactionTemplate", transactionTemplate); } @@ -93,6 +96,7 @@ void setUp() { @AfterAll static void afterAll() { EnvUtil.setEnvironment(null); + EmbeddedStorageContextHolder.cleanAllContext(); } @Test @@ -102,6 +106,14 @@ void testQueryOne1() { Long num = 1L; when(jdbcTemplate.queryForObject(sql, clazz)).thenReturn(num); assertEquals(operate.queryOne(sql, clazz), (Long) 1L); + when(jdbcTemplate.queryForObject(sql, clazz)).thenThrow(new IncorrectResultSizeDataAccessException("test", 1)); + assertNull(operate.queryOne(sql, clazz)); + reset(jdbcTemplate); + when(jdbcTemplate.queryForObject(sql, clazz)).thenThrow(new CannotGetJdbcConnectionException("test")); + assertThrows(CannotGetJdbcConnectionException.class, () -> operate.queryOne(sql, clazz)); + reset(jdbcTemplate); + when(jdbcTemplate.queryForObject(sql, clazz)).thenThrow(new NJdbcException("test", "OriginalExceptionName")); + assertThrows(NJdbcException.class, () -> operate.queryOne(sql, clazz)); } @Test @@ -114,6 +126,17 @@ void testQueryOne2() { Object[] args = new Object[] {configInfo.getId(), configInfo.getDataId(), configInfo.getGroup()}; when(jdbcTemplate.queryForObject(sql, args, MockConfigInfo.class)).thenReturn(configInfo); assertEquals(operate.queryOne(sql, args, MockConfigInfo.class), configInfo); + when(jdbcTemplate.queryForObject(sql, args, MockConfigInfo.class)).thenThrow( + new IncorrectResultSizeDataAccessException("test", 1)); + assertNull(operate.queryOne(sql, args, MockConfigInfo.class)); + reset(jdbcTemplate); + when(jdbcTemplate.queryForObject(sql, args, MockConfigInfo.class)).thenThrow( + new CannotGetJdbcConnectionException("test")); + assertThrows(CannotGetJdbcConnectionException.class, () -> operate.queryOne(sql, args, MockConfigInfo.class)); + reset(jdbcTemplate); + when(jdbcTemplate.queryForObject(sql, args, MockConfigInfo.class)).thenThrow( + new NJdbcException("test", "OriginalExceptionName")); + assertThrows(NJdbcException.class, () -> operate.queryOne(sql, args, MockConfigInfo.class)); } @Test @@ -126,6 +149,17 @@ void testQueryOne3() { Object[] args = new Object[] {configInfo.getId(), configInfo.getDataId(), configInfo.getGroup()}; when(jdbcTemplate.queryForObject(eq(sql), eq(args), any(RowMapper.class))).thenReturn(configInfo); assertEquals(operate.queryOne(sql, args, rowMapper), configInfo); + when(jdbcTemplate.queryForObject(eq(sql), eq(args), any(RowMapper.class))).thenThrow( + new IncorrectResultSizeDataAccessException("test", 1)); + assertNull(operate.queryOne(sql, args, rowMapper)); + reset(jdbcTemplate); + when(jdbcTemplate.queryForObject(eq(sql), eq(args), any(RowMapper.class))).thenThrow( + new CannotGetJdbcConnectionException("test")); + assertThrows(CannotGetJdbcConnectionException.class, () -> operate.queryOne(sql, args, rowMapper)); + reset(jdbcTemplate); + when(jdbcTemplate.queryForObject(eq(sql), eq(args), any(RowMapper.class))).thenThrow( + new NJdbcException("test", "OriginalExceptionName")); + assertThrows(NJdbcException.class, () -> operate.queryOne(sql, args, rowMapper)); } @Test @@ -174,6 +208,13 @@ void testQueryMany1() { configInfos.add(configInfo2); when(jdbcTemplate.query(eq(sql), eq(args), any(RowMapper.class))).thenReturn(configInfos); assertEquals(configInfos, operate.queryMany(sql, args, rowMapper)); + when(jdbcTemplate.query(eq(sql), eq(args), any(RowMapper.class))).thenThrow( + new CannotGetJdbcConnectionException("test")); + assertThrows(CannotGetJdbcConnectionException.class, () -> operate.queryMany(sql, args, rowMapper)); + reset(jdbcTemplate); + when(jdbcTemplate.query(eq(sql), eq(args), any(RowMapper.class))).thenThrow( + new NJdbcException("test", "OriginalExceptionName")); + assertThrows(NJdbcException.class, () -> operate.queryMany(sql, args, rowMapper)); } @Test @@ -197,6 +238,11 @@ void testQueryMany2() { when(jdbcTemplate.queryForList(sql, args)).thenReturn(resultList); assertEquals(operate.queryMany(sql, args), resultList); + when(jdbcTemplate.queryForList(sql, args)).thenThrow(new CannotGetJdbcConnectionException("test")); + assertThrows(CannotGetJdbcConnectionException.class, () -> operate.queryMany(sql, args)); + reset(jdbcTemplate); + when(jdbcTemplate.queryForList(sql, args)).thenThrow(new NJdbcException("test", "OriginalExceptionName")); + assertThrows(NJdbcException.class, () -> operate.queryMany(sql, args)); } @Test @@ -211,6 +257,17 @@ void testQueryMany3() { Class clazz = dataId1.getClass(); when(jdbcTemplate.queryForList(sql, args, clazz)).thenReturn(resultList); assertEquals(operate.queryMany(sql, args, clazz), resultList); + when(jdbcTemplate.queryForList(sql, args, clazz)).thenThrow( + new IncorrectResultSizeDataAccessException("test", 1)); + assertNull(operate.queryMany(sql, args, clazz)); + reset(jdbcTemplate); + when(jdbcTemplate.queryForList(sql, args, clazz)).thenThrow(new CannotGetJdbcConnectionException("test")); + assertThrows(CannotGetJdbcConnectionException.class, () -> operate.queryMany(sql, args, clazz)); + reset(jdbcTemplate); + when(jdbcTemplate.queryForList(sql, args, clazz)).thenThrow( + new NJdbcException("test", "OriginalExceptionName")); + assertThrows(NJdbcException.class, () -> operate.queryMany(sql, args, clazz)); + } @Test @@ -265,12 +322,41 @@ void testQueryMany6() { } @Test - void testDataImport() throws ExecutionException, InterruptedException { - RestResult errorResult = RestResult.builder().withCode(500).withMsg("null").withData(null).build(); - CompletableFuture> errorFuture = new CompletableFuture<>(); - errorFuture.complete(errorResult); - doReturn(errorFuture).when(operate).dataImport(null); - assertEquals(operate.dataImport(null).get(), errorResult); + void testDataImportSuccess() throws ExecutionException, InterruptedException, URISyntaxException { + File file = new File(getClass().getClassLoader().getResource("META-INF/test-derby-import.sql").toURI()); + int[] executeResult = new int[21]; + for (int i = executeResult.length - 1; i > executeResult.length - 6; i--) { + executeResult[i] = 1; + } + when(jdbcTemplate.batchUpdate(any(String[].class))).thenReturn(executeResult); + CompletableFuture> result = operate.dataImport(file); + TimeUnit.MILLISECONDS.sleep(1000L); + assertTrue(result.get().ok()); + assertEquals(200, result.get().getCode()); + } + + @Test + void testDataImportFailed() throws ExecutionException, InterruptedException, URISyntaxException { + File file = new File(getClass().getClassLoader().getResource("META-INF/test-derby-import.sql").toURI()); + int[] executeResult = new int[5]; + when(jdbcTemplate.batchUpdate(any(String[].class))).thenReturn(executeResult); + CompletableFuture> result = operate.dataImport(file); + TimeUnit.MILLISECONDS.sleep(1000L); + assertFalse(result.get().ok()); + assertEquals(500, result.get().getCode()); + assertNull(result.get().getMessage()); + } + + @Test + void testDataImportException() throws ExecutionException, InterruptedException, URISyntaxException { + File file = new File(getClass().getClassLoader().getResource("META-INF/test-derby-import.sql").toURI()); + when(jdbcTemplate.batchUpdate(any(String[].class))).thenThrow(new NJdbcException("test import failed")); + CompletableFuture> result = operate.dataImport(file); + TimeUnit.MILLISECONDS.sleep(1000L); + assertFalse(result.get().ok()); + assertEquals(500, result.get().getCode()); + assertEquals("com.alibaba.nacos.persistence.exception.NJdbcException: test import failed", + result.get().getMessage()); } @Test @@ -341,6 +427,15 @@ void testBlockUpdate2() { assertTrue(operate.blockUpdate(biConsumer)); } + @Test + void testBlockUpdateWithException() { + String sql = "UPDATE config_info SET data_id = 'test' WHERE id = 1;"; + EmbeddedStorageContextHolder.addSqlContext(sql); + when(transactionTemplate.execute(any(TransactionCallback.class))).thenThrow(new NJdbcException("test")); + assertThrows(NJdbcException.class, () -> operate.blockUpdate(biConsumer)); + assertTrue(EmbeddedStorageContextHolder.getCurrentSqlContext().isEmpty()); + } + @Test void testDoDataImport() { List modifyRequests = new ArrayList<>(); @@ -353,15 +448,4 @@ void testDoDataImport() { when(tempJdbcTemplate.batchUpdate(sql)).thenReturn(new int[] {1}); assertTrue(operate.doDataImport(tempJdbcTemplate, modifyRequests)); } - - @Test - void testFutureUpdate() throws ExecutionException, InterruptedException { - String sql = "SELECT 1"; - EmbeddedStorageContextHolder.addSqlContext(sql); - CompletableFuture future = new CompletableFuture<>(); - future.complete(true); - doAnswer((invocationOnMock) -> null).when(operate).futureUpdate(); - when(operate.futureUpdate()).thenReturn(future); - assertTrue(operate.futureUpdate().get()); - } } \ No newline at end of file diff --git a/persistence/src/test/java/com/alibaba/nacos/persistence/repository/embedded/sql/ModifyRequestTest.java b/persistence/src/test/java/com/alibaba/nacos/persistence/repository/embedded/sql/ModifyRequestTest.java new file mode 100644 index 00000000000..af885cf64df --- /dev/null +++ b/persistence/src/test/java/com/alibaba/nacos/persistence/repository/embedded/sql/ModifyRequestTest.java @@ -0,0 +1,35 @@ +/* + * Copyright 1999-2023 Alibaba Group Holding Ltd. + * + * Licensed 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 com.alibaba.nacos.persistence.repository.embedded.sql; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class ModifyRequestTest { + + @Test + void testToString() { + ModifyRequest request = new ModifyRequest(); + assertEquals("SQL{executeNo=0, sql='null', args=null}", request.toString()); + request.setRollBackOnUpdateFail(true); + request.setArgs(new Object[] {1, "test"}); + request.setSql("SELECT 1"); + request.setExecuteNo(1); + assertEquals("SQL{executeNo=1, sql='SELECT 1', args=[1, test]}", request.toString()); + } +} \ No newline at end of file diff --git a/persistence/src/test/java/com/alibaba/nacos/persistence/repository/embedded/sql/SelectRequestTest.java b/persistence/src/test/java/com/alibaba/nacos/persistence/repository/embedded/sql/SelectRequestTest.java new file mode 100644 index 00000000000..20ff0d66441 --- /dev/null +++ b/persistence/src/test/java/com/alibaba/nacos/persistence/repository/embedded/sql/SelectRequestTest.java @@ -0,0 +1,41 @@ +/* + * Copyright 1999-2023 Alibaba Group Holding Ltd. + * + * Licensed 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 com.alibaba.nacos.persistence.repository.embedded.sql; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class SelectRequestTest { + + @Test + void testBuild() { + SelectRequest.SelectRequestBuilder builder = SelectRequest.builder(); + builder.queryType(QueryType.QUERY_ONE_WITH_MAPPER_WITH_ARGS); + builder.sql("SELECT 1"); + builder.args(new Object[] {"1"}); + builder.className(Integer.class.getCanonicalName()); + SelectRequest request = builder.build(); + assertEquals(QueryType.QUERY_ONE_WITH_MAPPER_WITH_ARGS, request.getQueryType()); + assertEquals("SELECT 1", request.getSql()); + assertEquals("java.lang.Integer", request.getClassName()); + assertEquals(1, request.getArgs().length); + assertEquals("1", request.getArgs()[0]); + assertEquals("SelectRequest{queryType=0, sql='SELECT 1', args=[1], className='java.lang.Integer'}", + request.toString()); + } +} \ No newline at end of file diff --git a/persistence/src/test/java/com/alibaba/nacos/persistence/repository/extrnal/ExternalStoragePaginationHelperImplTest.java b/persistence/src/test/java/com/alibaba/nacos/persistence/repository/extrnal/ExternalStoragePaginationHelperImplTest.java new file mode 100644 index 00000000000..c36bc32f677 --- /dev/null +++ b/persistence/src/test/java/com/alibaba/nacos/persistence/repository/extrnal/ExternalStoragePaginationHelperImplTest.java @@ -0,0 +1,343 @@ +/* + * Copyright 1999-2023 Alibaba Group Holding Ltd. + * + * Licensed 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 com.alibaba.nacos.persistence.repository.extrnal; + +import com.alibaba.nacos.persistence.model.Page; +import com.alibaba.nacos.plugin.datasource.model.MapperResult; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class ExternalStoragePaginationHelperImplTest { + + private static final String QUERY_SQL = "SELECT * FROM config_info LIMIT 1"; + + private static final String QUERY_COUNT_SQL = "SELECT count(*) FROM config_info"; + + @Mock + JdbcTemplate jdbcTemplate; + + @Mock + RowMapper rowMapper; + + ExternalStoragePaginationHelperImpl externalStoragePaginationHelper; + + @BeforeEach + void setUp() { + externalStoragePaginationHelper = new ExternalStoragePaginationHelperImpl<>(jdbcTemplate); + } + + @AfterEach + void tearDown() { + } + + @Test + void testFetchPageWithIllegalPageInfo() { + assertThrows(IllegalArgumentException.class, + () -> externalStoragePaginationHelper.fetchPage("", "", new Object[] {}, 0, 0, null)); + assertThrows(IllegalArgumentException.class, + () -> externalStoragePaginationHelper.fetchPage("", "", new Object[] {}, 1, 0, null)); + } + + @Test + void testFetchPageWithoutResult() { + when(jdbcTemplate.queryForObject(QUERY_COUNT_SQL, new Object[] {}, Integer.class)).thenReturn(null); + assertThrows(IllegalArgumentException.class, + () -> externalStoragePaginationHelper.fetchPage(QUERY_COUNT_SQL, QUERY_SQL, new Object[] {}, 1, 1, + null)); + } + + @Test + void testFetchPageOnePage() { + when(jdbcTemplate.queryForObject(QUERY_COUNT_SQL, new Object[] {}, Integer.class)).thenReturn(1); + when(jdbcTemplate.query(QUERY_SQL, new Object[] {}, rowMapper)).thenReturn( + Collections.singletonList(new Object())); + Page actual = externalStoragePaginationHelper.fetchPage(QUERY_COUNT_SQL, QUERY_SQL, new Object[] {}, 1, + 1, rowMapper); + assertEquals(1, actual.getTotalCount()); + assertEquals(1, actual.getPageNumber()); + assertEquals(1, actual.getPagesAvailable()); + assertEquals(1, actual.getPageItems().size()); + } + + @Test + void testFetchPageMorePageFull() { + when(jdbcTemplate.queryForObject(QUERY_COUNT_SQL, new Object[] {}, Integer.class)).thenReturn(2); + when(jdbcTemplate.query(QUERY_SQL, new Object[] {}, rowMapper)).thenReturn( + Collections.singletonList(new Object())); + Page actual = externalStoragePaginationHelper.fetchPage(QUERY_COUNT_SQL, QUERY_SQL, new Object[] {}, 1, + 1, rowMapper); + assertEquals(2, actual.getTotalCount()); + assertEquals(1, actual.getPageNumber()); + assertEquals(2, actual.getPagesAvailable()); + assertEquals(1, actual.getPageItems().size()); + } + + @Test + void testFetchPageMorePageNotFull() { + when(jdbcTemplate.queryForObject(QUERY_COUNT_SQL, new Object[] {}, Integer.class)).thenReturn(3); + List pageItems = new LinkedList<>(); + pageItems.add(new Object()); + pageItems.add(new Object()); + when(jdbcTemplate.query(QUERY_SQL, new Object[] {}, rowMapper)).thenReturn(pageItems); + Page actual = externalStoragePaginationHelper.fetchPage(QUERY_COUNT_SQL, QUERY_SQL, new Object[] {}, 1, + 2, rowMapper); + assertEquals(3, actual.getTotalCount()); + assertEquals(1, actual.getPageNumber()); + assertEquals(2, actual.getPagesAvailable()); + assertEquals(2, actual.getPageItems().size()); + } + + @Test + void testFetchPageMorePageNextPage() { + when(jdbcTemplate.queryForObject(QUERY_COUNT_SQL, new Object[] {}, Integer.class)).thenReturn(3); + when(jdbcTemplate.query(QUERY_SQL, new Object[] {}, rowMapper)).thenReturn( + Collections.singletonList(new Object())); + Page actual = externalStoragePaginationHelper.fetchPage(QUERY_COUNT_SQL, QUERY_SQL, new Object[] {}, 2, + 2, rowMapper); + assertEquals(3, actual.getTotalCount()); + assertEquals(2, actual.getPageNumber()); + assertEquals(2, actual.getPagesAvailable()); + assertEquals(1, actual.getPageItems().size()); + } + + @Test + void testFetchPageMoreThanItemCount() { + when(jdbcTemplate.queryForObject(QUERY_COUNT_SQL, new Object[] {}, Integer.class)).thenReturn(3); + Page actual = externalStoragePaginationHelper.fetchPage(QUERY_COUNT_SQL, QUERY_SQL, new Object[] {}, 3, + 2, rowMapper); + assertEquals(3, actual.getTotalCount()); + assertEquals(3, actual.getPageNumber()); + assertEquals(2, actual.getPagesAvailable()); + assertEquals(0, actual.getPageItems().size()); + } + + @Test + void testFetchPageLimitWithIllegalPageInfo() { + assertThrows(IllegalArgumentException.class, + () -> externalStoragePaginationHelper.fetchPageLimit("", "", new Object[] {}, 0, 0, null)); + assertThrows(IllegalArgumentException.class, + () -> externalStoragePaginationHelper.fetchPageLimit("", "", new Object[] {}, 1, 0, null)); + } + + @Test + void testFetchPageLimitWithoutResult() { + when(jdbcTemplate.queryForObject(QUERY_COUNT_SQL, Integer.class)).thenReturn(null); + assertThrows(IllegalArgumentException.class, + () -> externalStoragePaginationHelper.fetchPageLimit(QUERY_COUNT_SQL, QUERY_SQL, new Object[] {}, 1, 1, + null)); + } + + @Test + void testFetchPageLimitOnePage() { + when(jdbcTemplate.queryForObject(QUERY_COUNT_SQL, Integer.class)).thenReturn(1); + when(jdbcTemplate.query(QUERY_SQL, new Object[] {}, rowMapper)).thenReturn( + Collections.singletonList(new Object())); + Page actual = externalStoragePaginationHelper.fetchPageLimit(QUERY_COUNT_SQL, QUERY_SQL, + new Object[] {}, 1, 1, rowMapper); + assertEquals(1, actual.getTotalCount()); + assertEquals(1, actual.getPageNumber()); + assertEquals(1, actual.getPagesAvailable()); + assertEquals(1, actual.getPageItems().size()); + } + + @Test + void testFetchPageLimitMorePageFull() { + when(jdbcTemplate.queryForObject(QUERY_COUNT_SQL, Integer.class)).thenReturn(2); + when(jdbcTemplate.query(QUERY_SQL, new Object[] {}, rowMapper)).thenReturn( + Collections.singletonList(new Object())); + Page actual = externalStoragePaginationHelper.fetchPageLimit(QUERY_COUNT_SQL, QUERY_SQL, + new Object[] {}, 1, 1, rowMapper); + assertEquals(2, actual.getTotalCount()); + assertEquals(1, actual.getPageNumber()); + assertEquals(2, actual.getPagesAvailable()); + assertEquals(1, actual.getPageItems().size()); + } + + @Test + void testFetchPageLimitMorePageNotFull() { + when(jdbcTemplate.queryForObject(QUERY_COUNT_SQL, Integer.class)).thenReturn(3); + List pageItems = new LinkedList<>(); + pageItems.add(new Object()); + pageItems.add(new Object()); + when(jdbcTemplate.query(QUERY_SQL, new Object[] {}, rowMapper)).thenReturn(pageItems); + Page actual = externalStoragePaginationHelper.fetchPageLimit(QUERY_COUNT_SQL, QUERY_SQL, + new Object[] {}, 1, 2, rowMapper); + assertEquals(3, actual.getTotalCount()); + assertEquals(1, actual.getPageNumber()); + assertEquals(2, actual.getPagesAvailable()); + assertEquals(2, actual.getPageItems().size()); + } + + @Test + void testFetchPageLimitMorePageNextPage() { + when(jdbcTemplate.queryForObject(QUERY_COUNT_SQL, Integer.class)).thenReturn(3); + when(jdbcTemplate.query(QUERY_SQL, new Object[] {}, rowMapper)).thenReturn( + Collections.singletonList(new Object())); + Page actual = externalStoragePaginationHelper.fetchPageLimit(QUERY_COUNT_SQL, QUERY_SQL, + new Object[] {}, 2, 2, rowMapper); + assertEquals(3, actual.getTotalCount()); + assertEquals(2, actual.getPageNumber()); + assertEquals(2, actual.getPagesAvailable()); + assertEquals(1, actual.getPageItems().size()); + } + + @Test + void testFetchPageLimitMoreThanItemCount() { + when(jdbcTemplate.queryForObject(QUERY_COUNT_SQL, Integer.class)).thenReturn(3); + Page actual = externalStoragePaginationHelper.fetchPageLimit(QUERY_COUNT_SQL, QUERY_SQL, + new Object[] {}, 3, 2, rowMapper); + assertEquals(3, actual.getTotalCount()); + assertEquals(3, actual.getPageNumber()); + assertEquals(2, actual.getPagesAvailable()); + assertEquals(0, actual.getPageItems().size()); + } + + @Test + void testFetchPageLimitWithPluginWithIllegalPageInfo() { + MapperResult countMapper = new MapperResult(QUERY_COUNT_SQL, new ArrayList<>()); + MapperResult queryMapper = new MapperResult(QUERY_SQL, new ArrayList<>()); + assertThrows(IllegalArgumentException.class, + () -> externalStoragePaginationHelper.fetchPageLimit(countMapper, queryMapper, 0, 0, null)); + assertThrows(IllegalArgumentException.class, + () -> externalStoragePaginationHelper.fetchPageLimit(countMapper, queryMapper, 1, 0, null)); + } + + @Test + void testFetchPageLimitWithPluginWithoutResult() { + MapperResult countMapper = new MapperResult(QUERY_COUNT_SQL, new ArrayList<>()); + MapperResult queryMapper = new MapperResult(QUERY_SQL, new ArrayList<>()); + when(jdbcTemplate.queryForObject(QUERY_COUNT_SQL, new Object[] {}, Integer.class)).thenReturn(null); + assertThrows(IllegalArgumentException.class, + () -> externalStoragePaginationHelper.fetchPageLimit(countMapper, queryMapper, 1, 1, null)); + } + + @Test + void testFetchPageLimitWithPluginPageOnePage() { + MapperResult countMapper = new MapperResult(QUERY_COUNT_SQL, new ArrayList<>()); + MapperResult queryMapper = new MapperResult(QUERY_SQL, new ArrayList<>()); + when(jdbcTemplate.queryForObject(QUERY_COUNT_SQL, new Object[] {}, Integer.class)).thenReturn(1); + when(jdbcTemplate.query(QUERY_SQL, new Object[] {}, rowMapper)).thenReturn( + Collections.singletonList(new Object())); + Page actual = externalStoragePaginationHelper.fetchPageLimit(countMapper, queryMapper, 1, 1, rowMapper); + assertEquals(1, actual.getTotalCount()); + assertEquals(1, actual.getPageNumber()); + assertEquals(1, actual.getPagesAvailable()); + assertEquals(1, actual.getPageItems().size()); + } + + @Test + void testFetchPageLimitWithPluginMorePageFull() { + MapperResult countMapper = new MapperResult(QUERY_COUNT_SQL, new ArrayList<>()); + MapperResult queryMapper = new MapperResult(QUERY_SQL, new ArrayList<>()); + when(jdbcTemplate.queryForObject(QUERY_COUNT_SQL, new Object[] {}, Integer.class)).thenReturn(2); + when(jdbcTemplate.query(QUERY_SQL, new Object[] {}, rowMapper)).thenReturn( + Collections.singletonList(new Object())); + Page actual = externalStoragePaginationHelper.fetchPageLimit(countMapper, queryMapper, 1, 1, rowMapper); + assertEquals(2, actual.getTotalCount()); + assertEquals(1, actual.getPageNumber()); + assertEquals(2, actual.getPagesAvailable()); + assertEquals(1, actual.getPageItems().size()); + } + + @Test + void testFetchPageLimitWithPluginMorePageNotFull() { + when(jdbcTemplate.queryForObject(QUERY_COUNT_SQL, new Object[] {}, Integer.class)).thenReturn(3); + List pageItems = new LinkedList<>(); + pageItems.add(new Object()); + pageItems.add(new Object()); + MapperResult countMapper = new MapperResult(QUERY_COUNT_SQL, new ArrayList<>()); + MapperResult queryMapper = new MapperResult(QUERY_SQL, new ArrayList<>()); + when(jdbcTemplate.query(QUERY_SQL, new Object[] {}, rowMapper)).thenReturn(pageItems); + Page actual = externalStoragePaginationHelper.fetchPageLimit(countMapper, queryMapper, 1, 2, rowMapper); + assertEquals(3, actual.getTotalCount()); + assertEquals(1, actual.getPageNumber()); + assertEquals(2, actual.getPagesAvailable()); + assertEquals(2, actual.getPageItems().size()); + } + + @Test + void testFetchPageLimitWithPluginMorePageNextPage() { + MapperResult countMapper = new MapperResult(QUERY_COUNT_SQL, new ArrayList<>()); + MapperResult queryMapper = new MapperResult(QUERY_SQL, new ArrayList<>()); + when(jdbcTemplate.queryForObject(QUERY_COUNT_SQL, new Object[] {}, Integer.class)).thenReturn(3); + when(jdbcTemplate.query(QUERY_SQL, new Object[] {}, rowMapper)).thenReturn( + Collections.singletonList(new Object())); + Page actual = externalStoragePaginationHelper.fetchPageLimit(countMapper, queryMapper, 2, 2, rowMapper); + assertEquals(3, actual.getTotalCount()); + assertEquals(2, actual.getPageNumber()); + assertEquals(2, actual.getPagesAvailable()); + assertEquals(1, actual.getPageItems().size()); + } + + @Test + void testFetchPageLimitWithPluginMoreThanItemCount() { + MapperResult countMapper = new MapperResult(QUERY_COUNT_SQL, new ArrayList<>()); + MapperResult queryMapper = new MapperResult(QUERY_SQL, new ArrayList<>()); + when(jdbcTemplate.queryForObject(QUERY_COUNT_SQL, new Object[] {}, Integer.class)).thenReturn(3); + Page actual = externalStoragePaginationHelper.fetchPageLimit(countMapper, queryMapper, 3, 2, rowMapper); + assertEquals(3, actual.getTotalCount()); + assertEquals(3, actual.getPageNumber()); + assertEquals(2, actual.getPagesAvailable()); + assertEquals(0, actual.getPageItems().size()); + } + + @Test + void testFetchPageLimitSimpleWithIllegalPageInfo() { + assertThrows(IllegalArgumentException.class, + () -> externalStoragePaginationHelper.fetchPageLimit(QUERY_SQL, new Object[] {}, 0, 0, null)); + assertThrows(IllegalArgumentException.class, + () -> externalStoragePaginationHelper.fetchPageLimit(QUERY_SQL, new Object[] {}, 1, 0, null)); + } + + @Test + void testFetchPageLimitSimpleWithData() { + List pageItems = new LinkedList<>(); + pageItems.add(new Object()); + pageItems.add(new Object()); + pageItems.add(new Object()); + when(jdbcTemplate.query(QUERY_SQL, new Object[] {}, rowMapper)).thenReturn(pageItems); + Page actual = externalStoragePaginationHelper.fetchPageLimit(QUERY_SQL, new Object[]{}, 3, 1, rowMapper); + assertEquals(0, actual.getTotalCount()); + assertEquals(0, actual.getPageNumber()); + assertEquals(0, actual.getPagesAvailable()); + assertEquals(3, actual.getPageItems().size()); + } + + @Test + void updateLimit() { + Object[] args = new Object[] {}; + externalStoragePaginationHelper.updateLimit(QUERY_SQL, args); + verify(jdbcTemplate).update(QUERY_SQL, args); + } +} \ No newline at end of file diff --git a/persistence/src/test/java/com/alibaba/nacos/persistence/utils/PersistenceExecutorTest.java b/persistence/src/test/java/com/alibaba/nacos/persistence/utils/PersistenceExecutorTest.java index 0aaa90a6518..d530c13d777 100644 --- a/persistence/src/test/java/com/alibaba/nacos/persistence/utils/PersistenceExecutorTest.java +++ b/persistence/src/test/java/com/alibaba/nacos/persistence/utils/PersistenceExecutorTest.java @@ -40,4 +40,21 @@ void testExecuteEmbeddedDump() throws InterruptedException { } + @Test + void testScheduleTask() throws InterruptedException { + final AtomicInteger count = new AtomicInteger(0); + Runnable runnable = count::incrementAndGet; + PersistenceExecutor.scheduleTask(runnable, 0, 300, TimeUnit.MILLISECONDS); + TimeUnit.MILLISECONDS.sleep(200); + assertEquals(1, count.get()); + } + + @Test + void testExecuteSnapshot() throws InterruptedException { + final AtomicInteger count = new AtomicInteger(0); + Runnable runnable = count::incrementAndGet; + PersistenceExecutor.executeSnapshot(runnable); + TimeUnit.MILLISECONDS.sleep(200); + assertEquals(1, count.get()); + } } \ No newline at end of file diff --git a/persistence/src/test/resources/META-INF/derby-schema.sql b/persistence/src/test/resources/META-INF/derby-schema.sql new file mode 100644 index 00000000000..601d38ab2e6 --- /dev/null +++ b/persistence/src/test/resources/META-INF/derby-schema.sql @@ -0,0 +1,227 @@ +build/* + * Copyright 1999-2018 Alibaba Group Holding Ltd. + * + * Licensed 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. + */ + +CREATE SCHEMA nacos AUTHORIZATION nacos; + +CREATE TABLE config_info ( + id bigint NOT NULL generated by default as identity, + data_id varchar(255) NOT NULL, + group_id varchar(128) NOT NULL, + tenant_id varchar(128) default '', + app_name varchar(128), + content CLOB, + md5 varchar(32) DEFAULT NULL, + gmt_create timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', + gmt_modified timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', + src_user varchar(128) DEFAULT NULL, + src_ip varchar(50) DEFAULT NULL, + c_desc varchar(256) DEFAULT NULL, + c_use varchar(64) DEFAULT NULL, + effect varchar(64) DEFAULT NULL, + type varchar(64) DEFAULT NULL, + c_schema LONG VARCHAR DEFAULT NULL, + encrypted_data_key LONG VARCHAR DEFAULT NULL, + constraint configinfo_id_key PRIMARY KEY (id), + constraint uk_configinfo_datagrouptenant UNIQUE (data_id,group_id,tenant_id)); + +CREATE INDEX configinfo_dataid_key_idx ON config_info(data_id); +CREATE INDEX configinfo_groupid_key_idx ON config_info(group_id); +CREATE INDEX configinfo_dataid_group_key_idx ON config_info(data_id, group_id); + +CREATE TABLE his_config_info ( + id bigint NOT NULL, + nid bigint NOT NULL generated by default as identity, + data_id varchar(255) NOT NULL, + group_id varchar(128) NOT NULL, + tenant_id varchar(128) default '', + app_name varchar(128), + content CLOB, + md5 varchar(32) DEFAULT NULL, + gmt_create timestamp NOT NULL DEFAULT '2010-05-05 00:00:00.000', + gmt_modified timestamp NOT NULL DEFAULT '2010-05-05 00:00:00.000', + src_user varchar(128), + src_ip varchar(50) DEFAULT NULL, + op_type char(10) DEFAULT NULL, + encrypted_data_key LONG VARCHAR DEFAULT NULL, + constraint hisconfiginfo_nid_key PRIMARY KEY (nid)); + +CREATE INDEX hisconfiginfo_dataid_key_idx ON his_config_info(data_id); +CREATE INDEX hisconfiginfo_gmt_create_idx ON his_config_info(gmt_create); +CREATE INDEX hisconfiginfo_gmt_modified_idx ON his_config_info(gmt_modified); + + +CREATE TABLE config_info_beta ( + id bigint NOT NULL generated by default as identity, + data_id varchar(255) NOT NULL, + group_id varchar(128) NOT NULL, + tenant_id varchar(128) default '', + app_name varchar(128), + content CLOB, + beta_ips varchar(1024), + md5 varchar(32) DEFAULT NULL, + gmt_create timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', + gmt_modified timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', + src_user varchar(128), + src_ip varchar(50) DEFAULT NULL, + encrypted_data_key LONG VARCHAR DEFAULT NULL, + constraint configinfobeta_id_key PRIMARY KEY (id), + constraint uk_configinfobeta_datagrouptenant UNIQUE (data_id,group_id,tenant_id)); + +CREATE TABLE config_info_tag ( + id bigint NOT NULL generated by default as identity, + data_id varchar(255) NOT NULL, + group_id varchar(128) NOT NULL, + tenant_id varchar(128) default '', + tag_id varchar(128) NOT NULL, + app_name varchar(128), + content CLOB, + md5 varchar(32) DEFAULT NULL, + gmt_create timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', + gmt_modified timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', + src_user varchar(128), + src_ip varchar(50) DEFAULT NULL, + constraint configinfotag_id_key PRIMARY KEY (id), + constraint uk_configinfotag_datagrouptenanttag UNIQUE (data_id,group_id,tenant_id,tag_id)); + +CREATE TABLE config_info_aggr ( + id bigint NOT NULL generated by default as identity, + data_id varchar(255) NOT NULL, + group_id varchar(128) NOT NULL, + tenant_id varchar(128) default '', + datum_id varchar(255) NOT NULL, + app_name varchar(128), + content CLOB, + gmt_modified timestamp NOT NULL DEFAULT '2010-05-05 00:00:00', + constraint configinfoaggr_id_key PRIMARY KEY (id), + constraint uk_configinfoaggr_datagrouptenantdatum UNIQUE (data_id,group_id,tenant_id,datum_id)); + +CREATE TABLE app_list ( + id bigint NOT NULL generated by default as identity, + app_name varchar(128) NOT NULL, + is_dynamic_collect_disabled smallint DEFAULT 0, + last_sub_info_collected_time timestamp DEFAULT '1970-01-01 08:00:00.0', + sub_info_lock_owner varchar(128), + sub_info_lock_time timestamp DEFAULT '1970-01-01 08:00:00.0', + constraint applist_id_key PRIMARY KEY (id), + constraint uk_appname UNIQUE (app_name)); + +CREATE TABLE app_configdata_relation_subs ( + id bigint NOT NULL generated by default as identity, + app_name varchar(128) NOT NULL, + data_id varchar(255) NOT NULL, + group_id varchar(128) NOT NULL, + gmt_modified timestamp DEFAULT '2010-05-05 00:00:00', + constraint configdatarelationsubs_id_key PRIMARY KEY (id), + constraint uk_app_sub_config_datagroup UNIQUE (app_name, data_id, group_id)); + + +CREATE TABLE app_configdata_relation_pubs ( + id bigint NOT NULL generated by default as identity, + app_name varchar(128) NOT NULL, + data_id varchar(255) NOT NULL, + group_id varchar(128) NOT NULL, + gmt_modified timestamp DEFAULT '2010-05-05 00:00:00', + constraint configdatarelationpubs_id_key PRIMARY KEY (id), + constraint uk_app_pub_config_datagroup UNIQUE (app_name, data_id, group_id)); + +CREATE TABLE config_tags_relation ( + id bigint NOT NULL, + tag_name varchar(128) NOT NULL, + tag_type varchar(64) DEFAULT NULL, + data_id varchar(255) NOT NULL, + group_id varchar(128) NOT NULL, + tenant_id varchar(128) DEFAULT '', + nid bigint NOT NULL generated by default as identity, + constraint config_tags_id_key PRIMARY KEY (nid), + constraint uk_configtagrelation_configidtag UNIQUE (id, tag_name, tag_type)); + +CREATE INDEX config_tags_tenant_id_idx ON config_tags_relation(tenant_id); + +CREATE TABLE group_capacity ( + id bigint NOT NULL generated by default as identity, + group_id varchar(128) DEFAULT '', + quota int DEFAULT 0, + usage int DEFAULT 0, + max_size int DEFAULT 0, + max_aggr_count int DEFAULT 0, + max_aggr_size int DEFAULT 0, + max_history_count int DEFAULT 0, + gmt_create timestamp DEFAULT '2010-05-05 00:00:00', + gmt_modified timestamp DEFAULT '2010-05-05 00:00:00', + constraint group_capacity_id_key PRIMARY KEY (id), + constraint uk_group_id UNIQUE (group_id)); + +CREATE TABLE tenant_capacity ( + id bigint NOT NULL generated by default as identity, + tenant_id varchar(128) DEFAULT '', + quota int DEFAULT 0, + usage int DEFAULT 0, + max_size int DEFAULT 0, + max_aggr_count int DEFAULT 0, + max_aggr_size int DEFAULT 0, + max_history_count int DEFAULT 0, + gmt_create timestamp DEFAULT '2010-05-05 00:00:00', + gmt_modified timestamp DEFAULT '2010-05-05 00:00:00', + constraint tenant_capacity_id_key PRIMARY KEY (id), + constraint uk_tenant_id UNIQUE (tenant_id)); + +CREATE TABLE tenant_info ( + id bigint NOT NULL generated by default as identity, + kp varchar(128) NOT NULL, + tenant_id varchar(128) DEFAULT '', + tenant_name varchar(128) DEFAULT '', + tenant_desc varchar(256) DEFAULT NULL, + create_source varchar(32) DEFAULT NULL, + gmt_create bigint NOT NULL, + gmt_modified bigint NOT NULL, + constraint tenant_info_id_key PRIMARY KEY (id), + constraint uk_tenant_info_kptenantid UNIQUE (kp,tenant_id)); +CREATE INDEX tenant_info_tenant_id_idx ON tenant_info(tenant_id); + +CREATE TABLE users ( + username varchar(50) NOT NULL PRIMARY KEY, + password varchar(500) NOT NULL, + enabled boolean NOT NULL DEFAULT true +); + +CREATE TABLE roles ( + username varchar(50) NOT NULL, + role varchar(50) NOT NULL, + constraint uk_username_role UNIQUE (username,role) +); + +CREATE TABLE permissions ( + role varchar(50) NOT NULL, + resource varchar(512) NOT NULL, + action varchar(8) NOT NULL, + constraint uk_role_permission UNIQUE (role,resource,action) +); + + +/******************************************/ +/* ipv6 support */ +/******************************************/ +ALTER TABLE `config_info_tag` +MODIFY COLUMN `src_ip` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT 'source ip' AFTER `src_user`; + +ALTER TABLE `his_config_info` +MODIFY COLUMN `src_ip` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL AFTER `src_user`; + +ALTER TABLE `config_info` +MODIFY COLUMN `src_ip` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT 'source ip' AFTER `src_user`; + +ALTER TABLE `config_info_beta` +MODIFY COLUMN `src_ip` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT 'source ip' AFTER `src_user`; \ No newline at end of file diff --git a/persistence/src/test/resources/META-INF/test-derby-import.sql b/persistence/src/test/resources/META-INF/test-derby-import.sql new file mode 100644 index 00000000000..180145f08b6 --- /dev/null +++ b/persistence/src/test/resources/META-INF/test-derby-import.sql @@ -0,0 +1,22 @@ +/* + * Copyright 1999-2023 Alibaba Group Holding Ltd. + * + * Licensed 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. + */ + +/* Just for test, not real table structure. */ +INSERT INTO `config_info` (id, data_id, group_id, namespace, content) VALUES (1, "test_id1", "test_group", "", "test_content"); +INSERT INTO `config_info` (id, data_id, group_id, namespace, content) VALUES (2, "test_id2", "test_group", "", "test_content"); +INSERT INTO `config_info` (id, data_id, group_id, namespace, content) VALUES (3, "test_id3", "test_group", "", "test_content"); +INSERT INTO `config_info` (id, data_id, group_id, namespace, content) VALUES (4, "test_id4", "test_group", "", "test_content"); +INSERT INTO `config_info` (id, data_id, group_id, namespace, content) VALUES (5, "test_id5", "test_group", "", "test_content");