package org.embulk.spi;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.List;
import org.embulk.EmbulkTestRuntime;
import org.embulk.config.TaskReport;
import org.embulk.config.ConfigSource;
import org.embulk.config.ConfigDiff;
import org.embulk.config.Task;
import org.embulk.config.TaskSource;
import org.embulk.spi.time.Timestamp;
import org.embulk.spi.Schema;
import org.junit.Rule;
import org.junit.Test;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import org.msgpack.value.ImmutableMapValue;
import static org.msgpack.value.ValueFactory.newBoolean;
import static org.msgpack.value.ValueFactory.newInteger;
import static org.msgpack.value.ValueFactory.newMap;
import static org.msgpack.value.ValueFactory.newString;
public class TestFileOutputRunner
{
@Rule
public EmbulkTestRuntime runtime = new EmbulkTestRuntime();
public interface PluginTask extends Task
{
}
private static class MockFileOutputPlugin implements FileOutputPlugin
{
Boolean transactionCompleted = null;
@Override
public ConfigDiff transaction(ConfigSource config, int taskCount,
FileOutputPlugin.Control control)
{
PluginTask task = config.loadConfig(PluginTask.class);
control.run(task.dump());
return Exec.newConfigDiff();
}
@Override
public ConfigDiff resume(TaskSource taskSource,
int taskCount,
FileOutputPlugin.Control control)
{
throw new UnsupportedOperationException();
}
@Override
public void cleanup(TaskSource taskSource,
int taskCount,
List<TaskReport> successTaskReports)
{
}
@Override
public TransactionalFileOutput open(TaskSource taskSource,
final int taskIndex)
{
return new TransactionalFileOutput()
{
@Override
public void nextFile()
{
}
@Override
public void add(Buffer buffer)
{
}
@Override
public void finish()
{
}
@Override
public void close()
{
}
@Override
public void abort()
{
transactionCompleted = false;
}
@Override
public TaskReport commit()
{
transactionCompleted = true;
return Exec.newTaskReport();
}
};
}
}
@Test
public void testMockFormatterIteration()
{
MockFileOutputPlugin fileOutputPlugin = new MockFileOutputPlugin();
final FileOutputRunner runner = new FileOutputRunner(fileOutputPlugin);
ImmutableList<ImmutableMap<String, Object>> columns = ImmutableList.of(
ImmutableMap.<String,Object>of("name", "col1", "type", "boolean", "option", ImmutableMap.of()),
ImmutableMap.<String,Object>of("name", "col2", "type", "long", "option", ImmutableMap.of()),
ImmutableMap.<String,Object>of("name", "col3", "type", "double", "option", ImmutableMap.of()),
ImmutableMap.<String,Object>of("name", "col4", "type", "string", "option", ImmutableMap.of()),
ImmutableMap.<String,Object>of("name", "col5", "type", "timestamp", "option", ImmutableMap.of()),
ImmutableMap.<String,Object>of("name", "col6", "type", "json", "option", ImmutableMap.of()));
ConfigSource config = Exec
.newConfigSource()
.set("type", "unused?")
.set("formatter",
ImmutableMap.of("type", "mock", "columns", columns));
final Schema schema = config.getNested("formatter")
.loadConfig(MockParserPlugin.PluginTask.class)
.getSchemaConfig().toSchema();
runner.transaction(config, schema, 1, new OutputPlugin.Control()
{
public List<TaskReport> run(final TaskSource outputTask)
{
TransactionalPageOutput tran = runner.open(outputTask, schema,
1);
boolean committed = false;
try {
ImmutableMapValue jsonValue = newMap(
newString("_c1"), newBoolean(true),
newString("_c2"), newInteger(10),
newString("_c3"), newString("embulk"),
newString("_c4"), newMap(newString("k"), newString("v"))
);
for (Page page : PageTestUtils.buildPage(
runtime.getBufferAllocator(), schema, true, 2L,
3.0D, "45", Timestamp.ofEpochMilli(678L), jsonValue, true, 2L,
3.0D, "45", Timestamp.ofEpochMilli(678L), jsonValue)) {
tran.add(page);
}
tran.commit();
committed = true;
} finally {
if (!committed) {
tran.abort();
}
tran.close();
}
return new ArrayList<TaskReport>();
}
});
assertEquals(true, fileOutputPlugin.transactionCompleted);
assertEquals(2, MockFormatterPlugin.records.size());
for (List<Object> record : MockFormatterPlugin.records) {
assertEquals(Boolean.TRUE, record.get(0));
assertEquals(2L, record.get(1));
assertEquals(3.0D, (Double) record.get(2), 0.1D);
assertEquals("45", record.get(3));
assertEquals(678L, ((Timestamp) record.get(4)).toEpochMilli());
assertEquals("{\"_c1\":true,\"_c2\":10,\"_c3\":\"embulk\",\"_c4\":{\"k\":\"v\"}}", record.get(5).toString());
}
}
@Test
public void testTransactionAborted()
{
MockFileOutputPlugin fileOutputPlugin = new MockFileOutputPlugin();
final FileOutputRunner runner = new FileOutputRunner(fileOutputPlugin);
ImmutableList<ImmutableMap<String, Object>> columns = ImmutableList.of(
ImmutableMap.<String,Object>of("name", "col1", "type", "boolean", "option", ImmutableMap.of()),
ImmutableMap.<String,Object>of("name", "col2", "type", "long", "option", ImmutableMap.of()),
ImmutableMap.<String,Object>of("name", "col3", "type", "double", "option", ImmutableMap.of()),
ImmutableMap.<String,Object>of("name", "col4", "type", "string", "option", ImmutableMap.of()),
ImmutableMap.<String,Object>of("name", "col5", "type", "timestamp", "option", ImmutableMap.of()),
ImmutableMap.<String,Object>of("name", "col6", "type", "json", "option", ImmutableMap.of()));
ConfigSource config = Exec
.newConfigSource()
.set("type", "unused?")
.set("formatter",
ImmutableMap.of("type", "mock", "columns", columns));
final Schema schema = config.getNested("formatter")
.loadConfig(MockParserPlugin.PluginTask.class)
.getSchemaConfig().toSchema();
try {
runner.transaction(config, schema, 1, new OutputPlugin.Control()
{
public List<TaskReport> run(final TaskSource outputTask)
{
TransactionalPageOutput tran = runner.open(outputTask,
schema, 1);
boolean committed = false;
try {
tran.add(null);
tran.commit();
committed = true;
} finally {
if (!committed) {
tran.abort();
}
tran.close();
}
return new ArrayList<TaskReport>();
}
});
} catch (NullPointerException npe) {
}
assertEquals(false, fileOutputPlugin.transactionCompleted);
}
}