/* * Copyright 2017 ThoughtWorks, Inc. * * 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.thoughtworks.go.server.database; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import com.thoughtworks.go.util.SystemEnvironment; import com.thoughtworks.go.util.TestFileUtil; import com.thoughtworks.go.util.ZipUtil; import org.apache.commons.dbcp.BasicDataSource; import org.junit.Assert; import static org.apache.commons.io.FileUtils.copyDirectory; import static org.apache.commons.io.FileUtils.deleteDirectory; import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertThat; public class DatabaseFixture { private File tmpDb; //This is what h2 reports for a text column static final String LONGVARCHAR = "VARCHAR(2147483647)"; public static final String TEXT = "CLOB(2147483647)"; private File templatesDir; public DatabaseFixture() { this.tmpDb = TestFileUtil.createTempFolder("h2database" + System.currentTimeMillis()); this.templatesDir = new File("db", "dbtemplate"); } public DatabaseFixture withTemplatesDir(String templatesDir) { this.templatesDir = new File(templatesDir); return this; } public SystemEnvironment env() throws IOException { return new SystemEnvironment(new File(tmpDb, "h2db").getCanonicalPath(), "9845"); } public void copyH2Db() { copyDb(new File(templatesDir(), "h2db")); } public void copyDb(File dir) { try { if (tmpDb.exists()) { deleteDirectory(tmpDb); tmpDb.mkdir(); } copyDirectory(dir, new File(tmpDb, "h2db")); copyDeltas(); } catch (IOException e) { throw new RuntimeException("Could not set up database for tests", e); } } public void copyDeltas() throws IOException { copyDirectory(new File(migrationsDir(), "h2deltas"), new File(tmpDb, "h2deltas")); } private File migrationsDir() { return new File("db/migrate"); } public void tearDown() { try { deleteDirectory(tmpDb); } catch (Exception e) { //ignore } } public File oldDb() { return new File(tmpDb, "hsqldb"); } public File backupFile() throws FileNotFoundException { File[] files = tmpDb.listFiles(); for (File file : files) { if (file.getName().contains("hsqldb-upgrade-backup")) { return file; } } throw new FileNotFoundException("No backup file found. Directory contains: " + Arrays.asList(files)); } public void copyOldDb() throws IOException { copyDirectory(new File(templatesDir(), "hsqldb"), oldDb()); } public File templatesDir() { return templatesDir; } public void copyOldDb(String oldDb) throws IOException { new ZipUtil().unzip(new File(templatesDir(), oldDb), oldDb()); } public void copyH2Db(String oldDb) throws IOException { File h2DbDir = new File(tmpDb, "h2db"); if (h2DbDir.exists()) { h2DbDir.delete(); h2DbDir.mkdirs(); } new ZipUtil().unzip(new File(templatesDir(), oldDb), h2DbDir); } public static void assertColumnType(BasicDataSource dataSource, String tableName, String columnName, String expected) throws SQLException { Connection connection = dataSource.getConnection(); try { ResultSet set = connection.getMetaData().getColumns(null, null, null, null); while (set.next()) { if (set.getString("TABLE_NAME").equalsIgnoreCase(tableName) && set.getString("COLUMN_NAME").equalsIgnoreCase(columnName)) { String typeName = set.getString("TYPE_NAME"); int typeWidth = set.getInt("COLUMN_SIZE"); String type = typeName + "(" + typeWidth + ")"; assertThat("Expected " + columnName + " to be " + expected + " type but was " + type, type, is(expected)); return; } } Assert.fail("Column " + columnName + " does not exist"); } finally { try { connection.close(); } catch (Exception ignored) { } } } public static int numericQuery(String query, H2Database h2Database) { return ((Long) query(query, h2Database)[0][0]).intValue(); } public static Object[][] query(String query, H2Database h2Database) { BasicDataSource source = h2Database.createDataSource(); Connection con = null; Statement stmt = null; ResultSet rs = null; try { con = source.getConnection(); stmt = con.createStatement(); rs = stmt.executeQuery(query); int columnCount = rs.getMetaData().getColumnCount(); List<Object[]> objects = new ArrayList<>(); while (rs.next()) { Object[] values = new Object[columnCount]; for (int i = 0; i < values.length; i++) { values[i] = rs.getObject(i+1); } objects.add(values); } return objects.toArray(new Object[0][0]); } catch (SQLException e) { throw new RuntimeException(e); } finally { try { assert stmt != null; stmt.close(); con.close(); assert rs != null; rs.close(); } catch (SQLException e) { throw new RuntimeException(e); } } } public static int update(String query, H2Database h2Database) { BasicDataSource source = h2Database.createDataSource(); Connection con = null; Statement stmt = null; try { con = source.getConnection(); stmt = con.createStatement(); return stmt.executeUpdate(query); } catch (SQLException e) { throw new RuntimeException(e); } finally { try { assert stmt != null; stmt.close(); con.close(); } catch (SQLException e) { throw new RuntimeException(e); } } } }