/** * Copyright (C) 2015 Orange * 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.francetelecom.clara.cloud.db.liquibase; import com.francetelecom.clara.cloud.test.database.DbaasDatabase; import liquibase.database.Database; import liquibase.diff.DiffResult; import liquibase.diff.ObjectDifferences; import liquibase.diff.output.DiffOutputControl; import liquibase.diff.output.ObjectChangeFilter; import liquibase.diff.output.StandardObjectChangeFilter; import liquibase.diff.output.changelog.DiffToChangeLog; import liquibase.exception.LiquibaseException; import liquibase.structure.DatabaseObject; import liquibase.structure.core.Column; import org.apache.commons.io.FileUtils; import org.junit.Test; import org.junit.runner.RunWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.core.io.Resource; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.xml.sax.SAXException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import java.io.*; import java.sql.SQLException; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; /** * This test compare a DB initialized using liquibase change log with a db initialiazed using hibernate automatic schema creation (hbm2ddl.auto = create) */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration() public abstract class CompareChangeLogWithHibernateAutoCreateIT { private static final Logger LOGGER = LoggerFactory.getLogger(CompareChangeLogWithHibernateAutoCreateIT.class.getName()); // 1st test DB initialized using hibernate in create-drop mode @Autowired DbaasDatabase db1; // 2nd test DB initialized using liquibase @Autowired DbaasDatabase db2; private final LiquibaseTestWrapper liquibaseWrapper = new LiquibaseTestWrapper(); @Test public void compare() throws SQLException, LiquibaseException, IOException, ParserConfigurationException { // Test exercise: Run diff DiffResult diffResult = liquibaseWrapper.diff( db1.getUrl(), db1.getUser(), db1.getPassword(), db2.getUrl(), db2.getUser(), db2.getPassword()); if (diffResult != null) { DiffOutputControl diffOutputControl = liquibaseWrapper.getTablespaceOnlyDiff(); ObjectChangeFilter customFilter = new ObjectChangeFilter() { StandardObjectChangeFilter columnWithDefaultValueFilter = new StandardObjectChangeFilter(StandardObjectChangeFilter.FilterType.EXCLUDE, "Column:middlewareprofileversion,Column:path,Column:servicename"); @Override public boolean includeMissing(DatabaseObject object, Database referenceDatabase, Database comparisionDatabase) { return true; } @Override public boolean includeUnexpected(DatabaseObject object, Database referenceDatabase, Database comparisionDatabase) { return true; } @Override public boolean includeChanged(DatabaseObject object, ObjectDifferences differences, Database referenceDatabase, Database comparisionDatabase) { LOGGER.debug("Check default value for {} - {} difference(s) found(s)", object, differences.getDifferences().size()); if (!(object instanceof Column)) { return true; } if (!columnWithDefaultValueFilter.includeChanged(object, differences, referenceDatabase, comparisionDatabase)) { differences.removeDifference("defaultValue"); } boolean includeChangeOnlyIfHasDifferences = differences.hasDifferences(); return includeChangeOnlyIfHasDifferences; } }; diffOutputControl.setObjectChangeFilter(customFilter); DiffToChangeLog changeLogWriter = new DiffToChangeLog(diffResult, diffOutputControl); changeLogWriter.setChangeSetAuthor("paas"); File shouldBeAnEmptyChangelog = File.createTempFile("changelogDiff-", ".xml", new File("target/")); try (PrintStream ps = new PrintStream(new FileOutputStream(shouldBeAnEmptyChangelog), true)) { changeLogWriter.print(ps); } boolean differenceFound = searchForDifferenceInXml(shouldBeAnEmptyChangelog);//FileUtils.contentEqualsIgnoreEOL(emptyChangelogFile, shouldBeAnEmptyChangelog, "UTF-8"); assertFalse("They are differences: \n" + FileUtils.readFileToString(shouldBeAnEmptyChangelog, "UTF-8"), differenceFound); } } private boolean searchForDifferenceInXml(File xmlFile) { boolean differenceFound = false; DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setValidating(false); factory.setIgnoringElementContentWhitespace(true); try { DocumentBuilder builder = factory.newDocumentBuilder(); Document document = builder.parse(xmlFile); Element databaseChangeLogRoot=document.getDocumentElement(); differenceFound=databaseChangeLogRoot.hasChildNodes(); // Do something with the document here. } catch (ParserConfigurationException | IOException |SAXException e) { LOGGER.info("Failed to parse xml file: {}",xmlFile,e); } return differenceFound; } private boolean hasDifference(DiffResult diffResult) { if (diffResult == null) { return false; } return diffResult.getChangedObjects().size() > 0 || diffResult.getMissingObjects().size() > 0 || diffResult.getUnexpectedObjects().size() > 0; } }