Validating SQL Script Conversion and Database Migration Workflow in Apollo Config
This test suite validates the SQL conversion functionality for Apollo’s H2 database implementation. It ensures proper conversion of MySQL scripts to H2-compatible format and verifies the execution order of migration scripts.
Test Coverage Overview
Implementation Analysis
Technical Details
Best Practices Demonstrated
apolloconfig/apollo
apollo-build-sql-converter/src/test/java/com/ctrip/framework/apollo/build/sql/converter/ApolloSqlConverterH2Test.java
/*
* Copyright 2024 Apollo Authors
*
* 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.ctrip.framework.apollo.build.sql.converter;
import java.nio.charset.StandardCharsets;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.core.io.PathResource;
import org.springframework.jdbc.datasource.SimpleDriverDataSource;
import org.springframework.jdbc.datasource.init.DatabasePopulatorUtils;
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
class ApolloSqlConverterH2Test {
@Test
void checkH2() {
String repositoryDir = ApolloSqlConverterUtil.getRepositoryDir();
String srcDir = repositoryDir + "/scripts/sql/src";
String checkerParentDir =
repositoryDir + "/apollo-build-sql-converter/target/scripts/sql/checker-h2";
String testSrcDir =
repositoryDir + "/apollo-build-sql-converter/src/test/resources/META-INF/sql/h2-test";
String testCheckerParentDir =
repositoryDir + "/apollo-build-sql-converter/target/scripts/sql/checker-h2-test";
// generate checker sql files
ApolloSqlConverterUtil.deleteDir(Paths.get(checkerParentDir));
SqlTemplateGist gists = ApolloSqlConverterUtil.getGists(repositoryDir);
SqlTemplateGist h2TestGist = gists.toBuilder()
.h2Function("\n"
+ "\n"
+ "-- H2 Function\n"
+ "-- ------------------------------------------------------------\n"
+ "CREATE ALIAS IF NOT EXISTS UNIX_TIMESTAMP FOR \"com.ctrip.framework.apollo.build.sql.converter.TestH2Function.unixTimestamp\";\n")
.build();
List<String> srcSqlList = ApolloSqlConverter.convert(repositoryDir, srcDir, checkerParentDir,
h2TestGist);
List<String> checkerSqlList = new ArrayList<>(srcSqlList.size());
for (String srcSql : srcSqlList) {
String checkerSql = ApolloSqlConverterUtil.replacePath(srcSql, srcDir,
checkerParentDir + "/sql/profiles/h2-default");
checkerSqlList.add(checkerSql);
}
// generate test checker sql files
ApolloSqlConverterUtil.deleteDir(Paths.get(testCheckerParentDir));
List<String> testSrcSqlList = ApolloSqlConverter.convert(repositoryDir, testSrcDir,
testCheckerParentDir, h2TestGist);
List<String> testCheckerSqlList = new ArrayList<>(testSrcSqlList.size());
for (String testSrcSql : testSrcSqlList) {
String testCheckerSql = ApolloSqlConverterUtil.replacePath(testSrcSql, testSrcDir,
testCheckerParentDir + "/sql/profiles/h2-default");
testCheckerSqlList.add(testCheckerSql);
}
this.checkSort(testSrcSqlList);
String h2Path = "test-h2";
this.checkConfigDatabase(h2Path, checkerSqlList, testCheckerSqlList);
this.checkPortalDatabase(h2Path, checkerSqlList, testCheckerSqlList);
}
private void checkSort(List<String> testSrcSqlList) {
int baseIndex = this.getIndex(testSrcSqlList, "apolloconfigdb-v000-v010-base.sql");
Assertions.assertTrue(baseIndex >= 0);
int beforeIndex = this.getIndex(testSrcSqlList, "apolloconfigdb-v000-v010-before.sql");
Assertions.assertTrue(beforeIndex >= 0);
int deltaIndex = this.getIndex(testSrcSqlList, "apolloconfigdb-v000-v010.sql");
Assertions.assertTrue(deltaIndex >= 0);
int afterIndex = this.getIndex(testSrcSqlList, "apolloconfigdb-v000-v010-after.sql");
Assertions.assertTrue(afterIndex >= 0);
// base < before < delta < after
Assertions.assertTrue(baseIndex < beforeIndex);
Assertions.assertTrue(beforeIndex < deltaIndex);
Assertions.assertTrue(deltaIndex < afterIndex);
}
private int getIndex(List<String> srcSqlList, String fileName) {
for (int i = 0; i < srcSqlList.size(); i++) {
String sqlFile = srcSqlList.get(i);
if (sqlFile.endsWith(fileName)) {
return i;
}
}
return -1;
}
private void checkConfigDatabase(String h2Path, List<String> checkerSqlList,
List<String> testCheckerSqlList) {
SimpleDriverDataSource configDataSource = new SimpleDriverDataSource();
configDataSource.setUrl("jdbc:h2:mem:~/" + h2Path
+ "/apollo-config-db;mode=mysql;DB_CLOSE_ON_EXIT=FALSE;DB_CLOSE_DELAY=-1;BUILTIN_ALIAS_OVERRIDE=TRUE;DATABASE_TO_UPPER=FALSE");
configDataSource.setDriverClass(org.h2.Driver.class);
ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
populator.setContinueOnError(false);
populator.setSeparator(";");
populator.setSqlScriptEncoding(StandardCharsets.UTF_8.name());
for (String sqlFile : testCheckerSqlList) {
if (sqlFile.contains("apolloconfigdb-")) {
populator.addScript(new PathResource(Paths.get(sqlFile)));
}
}
for (String sqlFile : checkerSqlList) {
if (sqlFile.contains("apolloconfigdb-")) {
populator.addScript(new PathResource(Paths.get(sqlFile)));
}
}
DatabasePopulatorUtils.execute(populator, configDataSource);
}
private void checkPortalDatabase(String h2Path, List<String> checkerSqlList,
List<String> testCheckerSqlList) {
SimpleDriverDataSource portalDataSource = new SimpleDriverDataSource();
portalDataSource.setUrl("jdbc:h2:mem:~/" + h2Path
+ "/apollo-portal-db;mode=mysql;DB_CLOSE_ON_EXIT=FALSE;DB_CLOSE_DELAY=-1;BUILTIN_ALIAS_OVERRIDE=TRUE;DATABASE_TO_UPPER=FALSE");
portalDataSource.setDriverClass(org.h2.Driver.class);
ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
populator.setContinueOnError(false);
populator.setSeparator(";");
populator.setSqlScriptEncoding(StandardCharsets.UTF_8.name());
for (String sqlFile : testCheckerSqlList) {
if (sqlFile.contains("apolloportaldb-")) {
populator.addScript(new PathResource(Paths.get(sqlFile)));
}
}
for (String sqlFile : checkerSqlList) {
if (sqlFile.contains("apolloportaldb-")) {
populator.addScript(new PathResource(Paths.get(sqlFile)));
}
}
DatabasePopulatorUtils.execute(populator, portalDataSource);
}
}