/** * Copyright 2011-2017 Asakusa Framework Team. * * 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.asakusafw.windgate.jdbc; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import org.junit.Rule; import org.junit.Test; import com.asakusafw.windgate.core.DriverScript; import com.asakusafw.windgate.core.ParameterList; import com.asakusafw.windgate.core.ProcessScript; import com.asakusafw.windgate.core.resource.DrainDriver; import com.asakusafw.windgate.core.resource.SourceDriver; import com.asakusafw.windgate.core.vocabulary.JdbcProcess; /** * Test for {@link JdbcResourceManipulator}. * @since 0.2.2 */ public class JdbcResourceManipulatorTest { /** * Test database. */ @Rule public H2Resource h2 = new H2Resource("testing") { @Override protected void before() throws Exception { executeFile("pair.sql"); } }; /** * Cleanups source. * @throws Exception if failed */ @Test public void cleanupSource() throws Exception { Map<String, String> conf = new HashMap<>(); conf.put(JdbcProcess.TABLE.key(), "PAIR"); conf.put(JdbcProcess.COLUMNS.key(), "KEY,VALUE"); conf.put(JdbcProcess.JDBC_SUPPORT.key(), PairSupport.class.getName()); ProcessScript<Pair> process = process(new DriverScript("jdbc", conf), dummy()); h2.execute("INSERT INTO PAIR (KEY, VALUE) VALUES (1, 'Hello1, world!')"); h2.execute("INSERT INTO PAIR (KEY, VALUE) VALUES (2, 'Hello2, world!')"); h2.execute("INSERT INTO PAIR (KEY, VALUE) VALUES (3, 'Hello3, world!')"); JdbcResourceManipulator manipulator = new JdbcResourceManipulator(profile(), new ParameterList()); assertThat(h2.count("PAIR"), is(3)); manipulator.cleanupSource(process); assertThat(h2.count("PAIR"), is(0)); } /** * Cleanups source with condition. * @throws Exception if failed */ @Test public void cleanupSource_with_condition() throws Exception { Map<String, String> conf = new HashMap<>(); conf.put(JdbcProcess.TABLE.key(), "PAIR"); conf.put(JdbcProcess.COLUMNS.key(), "KEY,VALUE"); conf.put(JdbcProcess.CONDITION.key(), "KEY = 10"); conf.put(JdbcProcess.JDBC_SUPPORT.key(), PairSupport.class.getName()); ProcessScript<Pair> process = process(new DriverScript("jdbc", conf), dummy()); h2.execute("INSERT INTO PAIR (KEY, VALUE) VALUES (1, 'Hello1, world!')"); h2.execute("INSERT INTO PAIR (KEY, VALUE) VALUES (2, 'Hello2, world!')"); h2.execute("INSERT INTO PAIR (KEY, VALUE) VALUES (3, 'Hello3, world!')"); JdbcResourceManipulator manipulator = new JdbcResourceManipulator(profile(), new ParameterList()); assertThat(h2.count("PAIR"), is(3)); manipulator.cleanupSource(process); assertThat(h2.count("PAIR"), is(0)); } /** * Cleanups source with custom truncate statement. * @throws Exception if failed */ @Test public void cleanupSource_with_custom_truncate() throws Exception { Map<String, String> conf = new HashMap<>(); conf.put(JdbcProcess.TABLE.key(), "PAIR"); conf.put(JdbcProcess.COLUMNS.key(), "KEY,VALUE"); conf.put(JdbcProcess.CUSTOM_TRUNCATE.key(), "DELETE FROM PAIR WHERE 0=1"); conf.put(JdbcProcess.JDBC_SUPPORT.key(), PairSupport.class.getName()); ProcessScript<Pair> process = process(new DriverScript("jdbc", conf), dummy()); h2.execute("INSERT INTO PAIR (KEY, VALUE) VALUES (1, 'Hello1, world!')"); h2.execute("INSERT INTO PAIR (KEY, VALUE) VALUES (2, 'Hello2, world!')"); h2.execute("INSERT INTO PAIR (KEY, VALUE) VALUES (3, 'Hello3, world!')"); JdbcResourceManipulator manipulator = new JdbcResourceManipulator(profile(), new ParameterList()); assertThat(h2.count("PAIR"), is(3)); manipulator.cleanupSource(process); assertThat(h2.count("PAIR"), is(0)); } /** * Cleanups source using modified truncate statement. * @throws Exception if failed */ @Test public void cleanupSource_modified() throws Exception { Map<String, String> conf = new HashMap<>(); conf.put(JdbcProcess.TABLE.key(), "PAIR"); conf.put(JdbcProcess.COLUMNS.key(), "KEY,VALUE"); conf.put(JdbcProcess.JDBC_SUPPORT.key(), PairSupport.class.getName()); ProcessScript<Pair> process = process(new DriverScript("jdbc", conf), dummy()); h2.execute("INSERT INTO PAIR (KEY, VALUE) VALUES (1, 'Hello1, world!')"); h2.execute("INSERT INTO PAIR (KEY, VALUE) VALUES (2, 'Hello2, world!')"); h2.execute("INSERT INTO PAIR (KEY, VALUE) VALUES (3, 'Hello3, world!')"); JdbcProfile profile = profile(); profile.setTruncateStatement("DELETE FROM {0} WHERE KEY = 1"); JdbcResourceManipulator manipulator = new JdbcResourceManipulator(profile, new ParameterList()); assertThat(h2.count("PAIR"), is(3)); manipulator.cleanupSource(process); assertThat(h2.count("PAIR"), is(2)); } /** * Attempts to cleanup source but the table is missing. * @throws Exception if failed */ @Test public void cleanupSource_missing_table() throws Exception { Map<String, String> conf = new HashMap<>(); conf.put(JdbcProcess.TABLE.key(), "MISSING"); conf.put(JdbcProcess.COLUMNS.key(), "KEY,VALUE"); conf.put(JdbcProcess.JDBC_SUPPORT.key(), PairSupport.class.getName()); ProcessScript<Pair> process = process(new DriverScript("jdbc", conf), dummy()); JdbcResourceManipulator manipulator = new JdbcResourceManipulator(profile(), new ParameterList()); manipulator.cleanupSource(process); // green } /** * Cleanups drain. * @throws Exception if failed */ @Test public void cleanupDrain() throws Exception { Map<String, String> conf = new HashMap<>(); conf.put(JdbcProcess.TABLE.key(), "PAIR"); conf.put(JdbcProcess.COLUMNS.key(), "KEY,VALUE"); conf.put(JdbcProcess.JDBC_SUPPORT.key(), PairSupport.class.getName()); conf.put(JdbcProcess.OPERATION.key(), JdbcProcess.OperationKind.INSERT_AFTER_TRUNCATE.value()); ProcessScript<Pair> process = process(dummy(), new DriverScript("jdbc", conf)); h2.execute("INSERT INTO PAIR (KEY, VALUE) VALUES (1, 'Hello1, world!')"); h2.execute("INSERT INTO PAIR (KEY, VALUE) VALUES (2, 'Hello2, world!')"); h2.execute("INSERT INTO PAIR (KEY, VALUE) VALUES (3, 'Hello3, world!')"); JdbcResourceManipulator manipulator = new JdbcResourceManipulator(profile(), new ParameterList()); assertThat(h2.count("PAIR"), is(3)); manipulator.cleanupDrain(process); assertThat(h2.count("PAIR"), is(0)); } /** * Cleanups drain with custom truncate. * @throws Exception if failed */ @Test public void cleanupDrain_with_custom_truncate() throws Exception { Map<String, String> conf = new HashMap<>(); conf.put(JdbcProcess.TABLE.key(), "PAIR"); conf.put(JdbcProcess.COLUMNS.key(), "KEY,VALUE"); conf.put(JdbcProcess.JDBC_SUPPORT.key(), PairSupport.class.getName()); conf.put(JdbcProcess.CUSTOM_TRUNCATE.key(), "DELETE FROM PAIR WHERE 0=1"); conf.put(JdbcProcess.OPERATION.key(), JdbcProcess.OperationKind.INSERT_AFTER_TRUNCATE.value()); ProcessScript<Pair> process = process(dummy(), new DriverScript("jdbc", conf)); h2.execute("INSERT INTO PAIR (KEY, VALUE) VALUES (1, 'Hello1, world!')"); h2.execute("INSERT INTO PAIR (KEY, VALUE) VALUES (2, 'Hello2, world!')"); h2.execute("INSERT INTO PAIR (KEY, VALUE) VALUES (3, 'Hello3, world!')"); JdbcResourceManipulator manipulator = new JdbcResourceManipulator(profile(), new ParameterList()); assertThat(h2.count("PAIR"), is(3)); manipulator.cleanupDrain(process); assertThat(h2.count("PAIR"), is(0)); } /** * Cleanups drain using modified truncate statement. * @throws Exception if failed */ @Test public void cleanupDrain_modified() throws Exception { Map<String, String> conf = new HashMap<>(); conf.put(JdbcProcess.TABLE.key(), "PAIR"); conf.put(JdbcProcess.COLUMNS.key(), "KEY,VALUE"); conf.put(JdbcProcess.JDBC_SUPPORT.key(), PairSupport.class.getName()); conf.put(JdbcProcess.OPERATION.key(), JdbcProcess.OperationKind.INSERT_AFTER_TRUNCATE.value()); ProcessScript<Pair> process = process(dummy(), new DriverScript("jdbc", conf)); h2.execute("INSERT INTO PAIR (KEY, VALUE) VALUES (1, 'Hello1, world!')"); h2.execute("INSERT INTO PAIR (KEY, VALUE) VALUES (2, 'Hello2, world!')"); h2.execute("INSERT INTO PAIR (KEY, VALUE) VALUES (3, 'Hello3, world!')"); JdbcProfile profile = profile(); profile.setTruncateStatement("DELETE FROM {0} WHERE KEY IN (1, 2)"); JdbcResourceManipulator manipulator = new JdbcResourceManipulator(profile, new ParameterList()); assertThat(h2.count("PAIR"), is(3)); manipulator.cleanupDrain(process); assertThat(h2.count("PAIR"), is(1)); } /** * Attempts to cleanup drain but the table is missing. * @throws Exception if failed */ @Test public void cleanupDrain_missing_table() throws Exception { Map<String, String> conf = new HashMap<>(); conf.put(JdbcProcess.TABLE.key(), "__MISSING__"); conf.put(JdbcProcess.COLUMNS.key(), "KEY,VALUE"); conf.put(JdbcProcess.JDBC_SUPPORT.key(), PairSupport.class.getName()); conf.put(JdbcProcess.OPERATION.key(), JdbcProcess.OperationKind.INSERT_AFTER_TRUNCATE.value()); ProcessScript<Pair> process = process(dummy(), new DriverScript("jdbc", conf)); JdbcResourceManipulator manipulator = new JdbcResourceManipulator(profile(), new ParameterList()); manipulator.cleanupDrain(process); // green } /** * Test method for {@link JdbcResourceManipulator#createSourceForSource(ProcessScript)}. * @throws Exception if failed */ @Test public void createSourceForSource() throws Exception { Map<String, String> conf = new HashMap<>(); conf.put(JdbcProcess.TABLE.key(), "PAIR"); conf.put(JdbcProcess.COLUMNS.key(), "KEY,VALUE"); conf.put(JdbcProcess.CONDITION.key(), "KEY > 2"); // should be ignored conf.put(JdbcProcess.JDBC_SUPPORT.key(), PairSupport.class.getName()); ProcessScript<Pair> process = process(new DriverScript("jdbc", conf), dummy()); h2.execute("INSERT INTO PAIR (KEY, VALUE) VALUES (1, 'Hello1, world!')"); h2.execute("INSERT INTO PAIR (KEY, VALUE) VALUES (2, 'Hello2, world!')"); h2.execute("INSERT INTO PAIR (KEY, VALUE) VALUES (3, 'Hello3, world!')"); h2.execute("INSERT INTO PAIR (KEY, VALUE) VALUES (4, 'Hello4, world!')"); h2.execute("INSERT INTO PAIR (KEY, VALUE) VALUES (5, 'Hello5, world!')"); JdbcResourceManipulator manipulator = new JdbcResourceManipulator(profile(), new ParameterList()); try (SourceDriver<Pair> driver = manipulator.createSourceForSource(process)) { driver.prepare(); test(driver, "Hello3, world!", "Hello4, world!", "Hello5, world!"); } } /** * Test method for {@link JdbcResourceManipulator#createDrainForSource(ProcessScript)}. * @throws Exception if failed */ @Test public void createDrainForSource() throws Exception { Map<String, String> conf = new HashMap<>(); conf.put(JdbcProcess.TABLE.key(), "PAIR"); conf.put(JdbcProcess.COLUMNS.key(), "KEY,VALUE"); conf.put(JdbcProcess.CONDITION.key(), "KEY > 10"); // should be ignored conf.put(JdbcProcess.JDBC_SUPPORT.key(), PairSupport.class.getName()); h2.execute("INSERT INTO PAIR (KEY, VALUE) VALUES (1, 'Hello1, world!')"); ProcessScript<Pair> process = process(new DriverScript("jdbc", conf), dummy()); JdbcResourceManipulator manipulator = new JdbcResourceManipulator(profile(), new ParameterList()); try (DrainDriver<Pair> driver = manipulator.createDrainForSource(process)) { driver.prepare(); driver.put(new Pair(2, "Hello2, world!")); driver.put(new Pair(3, "Hello3, world!")); } test("Hello1, world!", "Hello2, world!", "Hello3, world!"); } /** * Test method for {@link JdbcResourceManipulator#createSourceForDrain(ProcessScript)}. * @throws Exception if failed */ @Test public void createSourceForDrain() throws Exception { Map<String, String> conf = new HashMap<>(); conf.put(JdbcProcess.TABLE.key(), "PAIR"); conf.put(JdbcProcess.COLUMNS.key(), "KEY,VALUE"); conf.put(JdbcProcess.JDBC_SUPPORT.key(), PairSupport.class.getName()); conf.put(JdbcProcess.CUSTOM_TRUNCATE.key(), "DELETE FROM PAIR"); // should be ignored conf.put(JdbcProcess.OPERATION.key(), JdbcProcess.OperationKind.INSERT_AFTER_TRUNCATE.value()); ProcessScript<Pair> process = process(dummy(), new DriverScript("jdbc", conf)); h2.execute("INSERT INTO PAIR (KEY, VALUE) VALUES (1, 'Hello1, world!')"); h2.execute("INSERT INTO PAIR (KEY, VALUE) VALUES (2, 'Hello2, world!')"); h2.execute("INSERT INTO PAIR (KEY, VALUE) VALUES (3, 'Hello3, world!')"); JdbcResourceManipulator manipulator = new JdbcResourceManipulator(profile(), new ParameterList()); try (SourceDriver<Pair> driver = manipulator.createSourceForDrain(process)) { driver.prepare(); test(driver, "Hello1, world!", "Hello2, world!", "Hello3, world!"); } } /** * Test method for {@link JdbcResourceManipulator#createDrainForDrain(ProcessScript)}. * @throws Exception if failed */ @Test public void createDrainForDrain() throws Exception { Map<String, String> conf = new HashMap<>(); conf.put(JdbcProcess.TABLE.key(), "PAIR"); conf.put(JdbcProcess.COLUMNS.key(), "KEY,VALUE"); conf.put(JdbcProcess.JDBC_SUPPORT.key(), PairSupport.class.getName()); conf.put(JdbcProcess.CUSTOM_TRUNCATE.key(), "DELETE FROM PAIR"); // should be ignored conf.put(JdbcProcess.OPERATION.key(), JdbcProcess.OperationKind.INSERT_AFTER_TRUNCATE.value()); h2.execute("INSERT INTO PAIR (KEY, VALUE) VALUES (1, 'Hello1, world!')"); ProcessScript<Pair> process = process(dummy(), new DriverScript("jdbc", conf)); JdbcResourceManipulator manipulator = new JdbcResourceManipulator(profile(), new ParameterList()); try (DrainDriver<Pair> driver = manipulator.createDrainForDrain(process)) { driver.prepare(); driver.put(new Pair(2, "Hello2, world!")); driver.put(new Pair(3, "Hello3, world!")); } test("Hello1, world!", "Hello2, world!", "Hello3, world!"); } private void test(SourceDriver<Pair> source, String... expected) throws IOException { List<Pair> results = new ArrayList<>(); while (source.next()) { Pair pair = source.get(); results.add(new Pair(pair.key, pair.value)); } Collections.sort(results); List<String> actual = new ArrayList<>(); for (Pair row : results) { actual.add(row.value); } assertThat(actual, is(Arrays.asList(expected))); } private void test(String... expected) { List<List<Object>> results = h2.query("SELECT VALUE FROM PAIR ORDER BY KEY ASC"); List<String> actual = new ArrayList<>(); for (List<Object> row : results) { actual.add((String) row.get(0)); } assertThat(actual, is(Arrays.asList(expected))); } private ProcessScript<Pair> process(DriverScript source, DriverScript drain) { return new ProcessScript<>( "testing", "dummy", Pair.class, source, drain ); } private DriverScript dummy() { return new DriverScript("dummy", Collections.emptyMap()); } private JdbcProfile profile() { return new JdbcProfile( "jdbc", null, org.h2.Driver.class.getName(), h2.getJdbcUrl(), null, null, 100); } }