com.francetelecom.clara.cloud.db.liquibase.CompareChangeLogWithHibernateAutoCreateIT.java Source code

Java tutorial

Introduction

Here is the source code for com.francetelecom.clara.cloud.db.liquibase.CompareChangeLogWithHibernateAutoCreateIT.java

Source

/**
 * 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;
    }
}