// Copyright 2019 The Nomulus Authors. All Rights Reserved. // // 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 google.registry.sql.flyway; import static com.google.common.truth.Truth.assertThat; import static google.registry.testing.truth.TextDiffSubject.assertThat; import com.google.common.base.Joiner; import com.google.common.io.Resources; import google.registry.persistence.NomulusPostgreSql; import java.io.File; import java.net.URL; import java.nio.charset.StandardCharsets; import java.nio.file.Paths; import org.flywaydb.core.Flyway; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.testcontainers.containers.BindMode; import org.testcontainers.containers.Container; import org.testcontainers.containers.PostgreSQLContainer; /** Unit tests about Cloud SQL schema. */ @RunWith(JUnit4.class) public class SchemaTest { // Resource path that is mapped to the testcontainer instance. private static final String MOUNTED_RESOURCE_PATH = "testcontainer/mount"; // The mount point in the container. private static final String CONTAINER_MOUNT_POINT = "/tmp/pg_dump_out"; // pg_dump output file name. private static final String DUMP_OUTPUT_FILE = "dump.txt"; /** * The target database for schema deployment. * * <p>A resource path is mapped to this container in READ_WRITE mode to retrieve the deployed * schema generated by the 'pg_dump' command. Compared with communicating over stdout, it is * easier to update the golden schema this way. */ @Rule public PostgreSQLContainer sqlContainer = new PostgreSQLContainer<>(NomulusPostgreSql.getDockerTag()) .withClasspathResourceMapping( MOUNTED_RESOURCE_PATH, CONTAINER_MOUNT_POINT, BindMode.READ_WRITE); @Test public void deploySchema_success() throws Exception { Flyway flyway = Flyway.configure() .locations("sql/flyway") .dataSource( sqlContainer.getJdbcUrl(), sqlContainer.getUsername(), sqlContainer.getPassword()) .load(); // flyway.migrate() returns the number of newly pushed scripts. This is a variable // number as our schema evolves. assertThat(flyway.migrate()).isGreaterThan(0); flyway.validate(); Container.ExecResult execResult = sqlContainer.execInContainer( StandardCharsets.UTF_8, getSchemaDumpCommand(sqlContainer.getUsername(), sqlContainer.getDatabaseName())); if (execResult.getExitCode() != 0) { throw new RuntimeException(execResult.toString()); } URL dumpedSchema = Resources.getResource( Joiner.on(File.separatorChar).join(MOUNTED_RESOURCE_PATH, DUMP_OUTPUT_FILE)); assertThat(dumpedSchema) .hasSameContentAs(Resources.getResource("sql/schema/nomulus.golden.sql")); } private static String[] getSchemaDumpCommand(String username, String dbName) { return new String[] { "pg_dump", "-h", "localhost", "-U", username, "-f", Paths.get(CONTAINER_MOUNT_POINT, DUMP_OUTPUT_FILE).toString(), "--schema-only", "--no-owner", "--no-privileges", "--exclude-table", "flyway_schema_history", dbName }; } }