/**
* 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.runtime.core.context.RuntimeContext;
import com.asakusafw.runtime.core.context.RuntimeContext.ExecutionMode;
import com.asakusafw.runtime.core.context.RuntimeContextKeeper;
import com.asakusafw.windgate.core.DriverScript;
import com.asakusafw.windgate.core.GateScript;
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 JdbcResourceMirror}.
*/
public class JdbcResourceMirrorTest {
/**
* Keeps runtime context.
*/
@Rule
public final RuntimeContextKeeper rc = new RuntimeContextKeeper();
/**
* Test database.
*/
@Rule
public H2Resource h2 = new H2Resource("testing") {
@Override
protected void before() throws Exception {
executeFile("pair.sql");
}
};
/**
* Simple source test.
* @throws Exception if failed
*/
@Test
public void source_simple() 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());
GateScript script = script(process);
h2.execute("INSERT INTO PAIR (KEY, VALUE) VALUES (1, 'Hello, world!')");
try (JdbcResourceMirror resource = new JdbcResourceMirror(profile(), new ParameterList())) {
resource.prepare(script);
try (SourceDriver<Pair> source = resource.createSource(process)) {
source.prepare();
test(source, "Hello, world!");
}
}
}
/**
* Many objects from source.
* @throws Exception if failed
*/
@Test
public void source_many() 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());
GateScript script = script(process);
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!')");
try (JdbcResourceMirror resource = new JdbcResourceMirror(profile(), new ParameterList())) {
resource.prepare(script);
try (SourceDriver<Pair> source = resource.createSource(process)) {
source.prepare();
test(source, "Hello1, world!", "Hello2, world!", "Hello3, world!");
}
}
}
/**
* Source with condition.
* @throws Exception if failed
*/
@Test
public void source_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.JDBC_SUPPORT.key(), PairSupport.class.getName());
conf.put(JdbcProcess.CONDITION.key(), "KEY > 3");
ProcessScript<Pair> process = process(new DriverScript("jdbc", conf), dummy());
GateScript script = script(process);
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!')");
try (JdbcResourceMirror resource = new JdbcResourceMirror(profile(), new ParameterList())) {
resource.prepare(script);
try (SourceDriver<Pair> source = resource.createSource(process)) {
source.prepare();
test(source, "Hello4, world!", "Hello5, world!");
}
}
}
/**
* Source with parameterized condition.
* @throws Exception if failed
*/
@Test
public void source_condition_parameterized() 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.CONDITION.key(), "KEY <= ${max}");
ProcessScript<Pair> process = process(new DriverScript("jdbc", conf), dummy());
GateScript script = script(process);
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!')");
try (JdbcResourceMirror resource = new JdbcResourceMirror(
profile(),
new ParameterList(Collections.singletonMap("max", "2")))) {
resource.prepare(script);
try (SourceDriver<Pair> source = resource.createSource(process)) {
source.prepare();
test(source, "Hello1, world!", "Hello2, world!");
}
}
}
/**
* source test in simulated.
* @throws Exception if failed
*/
@Test
public void source_sim() throws Exception {
RuntimeContext.set(RuntimeContext.DEFAULT.mode(ExecutionMode.SIMULATION));
h2.execute("DROP TABLE PAIR;");
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());
GateScript script = script(process);
try (JdbcResourceMirror resource = new JdbcResourceMirror(profile(), new ParameterList())) {
assertThat(RuntimeContext.get().canExecute(resource), is(true));
resource.prepare(script);
try (SourceDriver<Pair> source = resource.createSource(process)) {
assertThat(RuntimeContext.get().canExecute(source), is(false));
}
}
}
/**
* Source with invalid parameterized condition.
* @throws Exception if failed
*/
@Test
public void source_condition_invalid_parameterized() 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.CONDITION.key(), "KEY <= ${INVALID}");
ProcessScript<Pair> process = process(new DriverScript("jdbc", conf), dummy());
GateScript script = script(process);
try (JdbcResourceMirror resource = new JdbcResourceMirror(profile(), new ParameterList())) {
try {
resource.prepare(script);
fail();
} catch (IOException e) {
// ok.
}
}
}
/**
* Source with invalid model.
* @throws Exception if failed
*/
@Test
public void source_invalid_model() 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(), VoidSupport.class.getName());
ProcessScript<Void> process = new ProcessScript<>(
"invalid",
"testing",
Void.class,
new DriverScript("jdbc", conf),
dummy());
GateScript script = script(process);
try (JdbcResourceMirror resource = new JdbcResourceMirror(profile(), new ParameterList())) {
try {
resource.prepare(script);
fail();
} catch (IOException e) {
// ok.
}
}
}
/**
* Simple drain test.
* @throws Exception if failed
*/
@Test
public void drain_simple() 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));
GateScript script = script(process);
try (JdbcResourceMirror resource = new JdbcResourceMirror(profile(), new ParameterList())) {
resource.prepare(script);
try (DrainDriver<Pair> drain = resource.createDrain(process)) {
drain.prepare();
drain.put(new Pair(1, "Hello, world!"));
}
test("Hello, world!");
}
}
/**
* Many objects into drain.
* @throws Exception if failed
*/
@Test
public void drain_many() 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));
GateScript script = script(process);
try (JdbcResourceMirror resource = new JdbcResourceMirror(profile(), new ParameterList())) {
resource.prepare(script);
try (DrainDriver<Pair> drain = resource.createDrain(process)) {
drain.prepare();
drain.put(new Pair(1, "Hello1, world!"));
drain.put(new Pair(2, "Hello2, world!"));
drain.put(new Pair(3, "Hello3, world!"));
}
test("Hello1, world!", "Hello2, world!", "Hello3, world!");
}
}
/**
* drain test in simulated.
* @throws Exception if failed
*/
@Test
public void drain_sim() throws Exception {
RuntimeContext.set(RuntimeContext.DEFAULT.mode(ExecutionMode.SIMULATION));
h2.execute("DROP TABLE PAIR;");
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));
GateScript script = script(process);
try (JdbcResourceMirror resource = new JdbcResourceMirror(profile(), new ParameterList())) {
assertThat(RuntimeContext.get().canExecute(resource), is(true));
resource.prepare(script);
try (DrainDriver<Pair> drain = resource.createDrain(process)) {
assertThat(RuntimeContext.get().canExecute(drain), is(false));
}
}
}
/**
* With invalid operation (missing).
* @throws Exception if failed
*/
@Test
public void invalid_drain_operation_missing() 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(dummy(), new DriverScript("jdbc", conf));
GateScript script = script(process);
try (JdbcResourceMirror resource = new JdbcResourceMirror(profile(), new ParameterList())) {
try {
resource.prepare(script);
fail();
} catch (IOException e) {
// ok.
}
}
}
/**
* With invalid operation (missing).
* @throws Exception if failed
*/
@Test
public void invalid_drain_operation_unknown() 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(), "__INVALID");
ProcessScript<Pair> process = process(dummy(), new DriverScript("jdbc", conf));
GateScript script = script(process);
try (JdbcResourceMirror resource = new JdbcResourceMirror(profile(), new ParameterList())) {
try {
resource.prepare(script);
fail();
} catch (IOException e) {
// ok.
}
}
}
/**
* With invalid table (unspecified).
* @throws Exception if failed
*/
@Test
public void invalid_table_missing() throws Exception {
Map<String, String> conf = new HashMap<>();
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());
GateScript script = script(process);
try (JdbcResourceMirror resource = new JdbcResourceMirror(profile(), new ParameterList())) {
try {
resource.prepare(script);
fail();
} catch (IOException e) {
// ok.
}
}
}
/**
* With invalid table (empty).
* @throws Exception if failed
*/
@Test
public void invalid_table_empty() throws Exception {
Map<String, String> conf = new HashMap<>();
conf.put(JdbcProcess.TABLE.key(), "");
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());
GateScript script = script(process);
try (JdbcResourceMirror resource = new JdbcResourceMirror(profile(), new ParameterList())) {
try {
resource.prepare(script);
fail();
} catch (IOException e) {
// ok.
}
}
}
/**
* With invalid columns (missing).
* @throws Exception if failed
*/
@Test
public void invalid_columns_missing() throws Exception {
Map<String, String> conf = new HashMap<>();
conf.put(JdbcProcess.TABLE.key(), "PAIR");
conf.put(JdbcProcess.JDBC_SUPPORT.key(), PairSupport.class.getName());
ProcessScript<Pair> process = process(new DriverScript("jdbc", conf), dummy());
GateScript script = script(process);
try (JdbcResourceMirror resource = new JdbcResourceMirror(profile(), new ParameterList())) {
try {
resource.prepare(script);
fail();
} catch (IOException e) {
// ok.
}
}
}
/**
* With invalid columns (empty).
* @throws Exception if failed
*/
@Test
public void invalid_columns_empty() throws Exception {
Map<String, String> conf = new HashMap<>();
conf.put(JdbcProcess.TABLE.key(), "PAIR");
conf.put(JdbcProcess.COLUMNS.key(), "");
conf.put(JdbcProcess.JDBC_SUPPORT.key(), PairSupport.class.getName());
ProcessScript<Pair> process = process(new DriverScript("jdbc", conf), dummy());
GateScript script = script(process);
try (JdbcResourceMirror resource = new JdbcResourceMirror(profile(), new ParameterList())) {
try {
resource.prepare(script);
fail();
} catch (IOException e) {
// ok.
}
}
}
/**
* With invalid support (missing).
* @throws Exception if failed
*/
@Test
public void invalid_support_missing() throws Exception {
Map<String, String> conf = new HashMap<>();
conf.put(JdbcProcess.TABLE.key(), "PAIR");
conf.put(JdbcProcess.COLUMNS.key(), "KEY,VALUE");
ProcessScript<Pair> process = process(new DriverScript("jdbc", conf), dummy());
GateScript script = script(process);
try (JdbcResourceMirror resource = new JdbcResourceMirror(profile(), new ParameterList())) {
try {
resource.prepare(script);
fail();
} catch (IOException e) {
// ok.
}
}
}
/**
* With invalid support (unknown classs).
* @throws Exception if failed
*/
@Test
public void invalid_support_unknown() 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(), "__INVALID");
ProcessScript<Pair> process = process(new DriverScript("jdbc", conf), dummy());
GateScript script = script(process);
try (JdbcResourceMirror resource = new JdbcResourceMirror(profile(), new ParameterList())) {
try {
resource.prepare(script);
fail();
} catch (IOException e) {
// ok.
}
}
}
/**
* With invalid support (inconsistent support class).
* @throws Exception if failed
*/
@Test
public void invalid_support_class() 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(), Pair.class.getName());
ProcessScript<Pair> process = process(new DriverScript("jdbc", conf), dummy());
GateScript script = script(process);
try (JdbcResourceMirror resource = new JdbcResourceMirror(profile(), new ParameterList())) {
try {
resource.prepare(script);
fail();
} catch (IOException e) {
// ok.
}
}
}
/**
* With invalid support (cannot create objects).
* @throws Exception if failed
*/
@Test
public void invalid_support_failnew() 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(), SupportWithPrivateConstructor.class.getName());
ProcessScript<Pair> process = process(new DriverScript("jdbc", conf), dummy());
GateScript script = script(process);
try (JdbcResourceMirror resource = new JdbcResourceMirror(profile(), new ParameterList())) {
try {
resource.prepare(script);
fail();
} catch (IOException e) {
// ok.
}
}
}
/**
* With invalid support (inconsistent).
* @throws Exception if failed
*/
@Test
public void invalid_support_inconsistent() 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(), VoidSupport.class.getName());
ProcessScript<Pair> process = process(new DriverScript("jdbc", conf), dummy());
GateScript script = script(process);
try (JdbcResourceMirror resource = new JdbcResourceMirror(profile(), new ParameterList())) {
try {
resource.prepare(script);
fail();
} catch (IOException e) {
// ok.
}
}
}
/**
* With invalid support (invalid columns).
* @throws Exception if failed
*/
@Test
public void invalid_support_unsupported() throws Exception {
Map<String, String> conf = new HashMap<>();
conf.put(JdbcProcess.TABLE.key(), "PAIR");
conf.put(JdbcProcess.COLUMNS.key(), "VALUE,KEY");
conf.put(JdbcProcess.JDBC_SUPPORT.key(), PairSupport.class.getName());
ProcessScript<Pair> process = process(new DriverScript("jdbc", conf), dummy());
GateScript script = script(process);
try (JdbcResourceMirror resource = new JdbcResourceMirror(profile(), new ParameterList())) {
try {
resource.prepare(script);
fail();
} catch (IOException e) {
// ok.
}
}
}
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 GateScript script(ProcessScript<?>... processes) {
return new GateScript("testing", Arrays.asList(processes));
}
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);
}
}