/** * 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.testdriver.directio; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Scanner; import org.apache.hadoop.io.Text; import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; import com.asakusafw.runtime.directio.DataFormat; import com.asakusafw.runtime.directio.hadoop.HadoopDataSource; import com.asakusafw.runtime.directio.hadoop.HadoopDataSourceProfile; import com.asakusafw.runtime.io.ModelOutput; import com.asakusafw.runtime.windows.WindowsSupport; import com.asakusafw.testdriver.core.SpiImporterPreparator; /** * Test for {@link DirectFileInputPreparator}. */ @RunWith(Parameterized.class) public class DirectFileInputPreparatorTest { /** * Windows platform support. */ @ClassRule public static final WindowsSupport WINDOWS_SUPPORT = new WindowsSupport(); /** * Profile context. */ @Rule public final ProfileContext profile = new ProfileContext(); /** * A temporary folder. */ @Rule public final TemporaryFolder folder = new TemporaryFolder(); private final Class<? extends DataFormat<Text>> format; /** * Returns the parameters. * @return the parameters */ @Parameters public static List<Object[]> data() { return Arrays.asList(new Object[][] { { MockStreamFormat.class }, { MockFileFormat.class }, }); } /** * Creates a new instance. * @param format the format. */ public DirectFileInputPreparatorTest(Class<? extends DataFormat<Text>> format) { this.format = format; } /** * truncate. * @throws Exception if failed */ @Test public void truncate() throws Exception { profile.add("root", HadoopDataSource.class, "/"); profile.add("root", HadoopDataSourceProfile.KEY_PATH, folder.getRoot().toURI().toURL().toString()); profile.put(); DirectFileInputPreparator testee = new DirectFileInputPreparator(); File file = put("base/hoge.txt", "Hello, world!"); File deep = put("base/d/e/e/p/hoge.txt", "Hello, world!"); File outer = put("outer/hoge.txt", "Hello, world!"); assertThat(file.exists(), is(true)); assertThat(deep.exists(), is(true)); assertThat(outer.exists(), is(true)); testee.truncate( new MockInputDescription("base", "something", format), profile.getTextContext()); assertThat(file.exists(), is(false)); assertThat(deep.exists(), is(false)); assertThat(outer.exists(), is(true)); } /** * truncate empty target. * @throws Exception if failed */ @Test public void truncate_empty() throws Exception { profile.add("root", HadoopDataSource.class, "/"); profile.add("root", HadoopDataSourceProfile.KEY_PATH, folder.getRoot().toURI().toURL().toString()); profile.put(); DirectFileInputPreparator testee = new DirectFileInputPreparator(); testee.truncate( new MockInputDescription("base", "something", format), profile.getTextContext()); } /** * truncate with variables in path. * @throws Exception if failed */ @Test public void truncate_variable() throws Exception { profile.add("root", HadoopDataSource.class, "/"); profile.add("root", HadoopDataSourceProfile.KEY_PATH, folder.getRoot().toURI().toURL().toString()); profile.put(); DirectFileInputPreparator testee = new DirectFileInputPreparator(); File file = put("base/hoge.txt", "Hello, world!"); File deep = put("base/d/e/e/p/hoge.txt", "Hello, world!"); File outer = put("outer/hoge.txt", "Hello, world!"); assertThat(file.exists(), is(true)); assertThat(deep.exists(), is(true)); assertThat(outer.exists(), is(true)); testee.truncate( new MockInputDescription("${target}", "something", format), profile.getTextContext("target", "base")); assertThat(file.exists(), is(false)); assertThat(deep.exists(), is(false)); assertThat(outer.exists(), is(true)); } /** * simple output. * @throws Exception if failed */ @Test public void createOutput() throws Exception { profile.add("root", HadoopDataSource.class, "/"); profile.add("root", HadoopDataSourceProfile.KEY_PATH, folder.getRoot().toURI().toURL().toString()); profile.put(); DirectFileInputPreparator testee = new DirectFileInputPreparator(); ModelOutput<Text> output = testee.createOutput( new MockTextDefinition(), new MockInputDescription("base", "input.txt", format), profile.getTextContext()); put(output, "Hello, world!"); assertThat(get("base/input.txt"), is(Arrays.asList("Hello, world!"))); } /** * output multiple records. * @throws Exception if failed */ @Test public void createOutput_multirecord() throws Exception { profile.add("root", HadoopDataSource.class, "/"); profile.add("root", HadoopDataSourceProfile.KEY_PATH, folder.getRoot().toURI().toURL().toString()); profile.put(); DirectFileInputPreparator testee = new DirectFileInputPreparator(); ModelOutput<Text> output = testee.createOutput( new MockTextDefinition(), new MockInputDescription("base", "input.txt", format), profile.getTextContext()); put(output, "Hello1", "Hello2", "Hello3"); List<String> list = get("base/input.txt"); assertThat(list.size(), is(3)); assertThat(list, hasItem("Hello1")); assertThat(list, hasItem("Hello2")); assertThat(list, hasItem("Hello3")); } /** * output with variables. * @throws Exception if failed */ @Test public void createOutput_variables() throws Exception { profile.add("vars", HadoopDataSource.class, "base"); profile.add("vars", new File(folder.getRoot(), "testing")); profile.put(); DirectFileInputPreparator testee = new DirectFileInputPreparator(); ModelOutput<Text> output = testee.createOutput( new MockTextDefinition(), new MockInputDescription("${vbase}", "${vinput}.txt", format), profile.getTextContext("vbase", "base", "vinput", "input")); put(output, "Hello, world!"); assertThat(get("testing/input.txt"), is(Arrays.asList("Hello, world!"))); } /** * output with placeholders. * @throws Exception if failed */ @Test public void createInput_placeholders() throws Exception { profile.add("root", HadoopDataSource.class, "/"); profile.add("root", HadoopDataSourceProfile.KEY_PATH, folder.getRoot().toURI().toURL().toString()); profile.put(); DirectFileInputPreparator testee = new DirectFileInputPreparator(); ModelOutput<Text> output = testee.createOutput( new MockTextDefinition(), new MockInputDescription("base", "{alpha|beta|gamma/data}/{a/x|b|c}-*.csv", format), profile.getTextContext()); put(output, "Hello, world!"); List<File> files = find("base"); assertThat(files.toString(), files.size(), is(1)); assertThat(get(files.get(0)), is(Arrays.asList("Hello, world!"))); } /** * output with placeholders. * @throws Exception if failed */ @Test public void createOutput_placeholders() throws Exception { profile.add("root", HadoopDataSource.class, "/"); profile.add("root", HadoopDataSourceProfile.KEY_PATH, folder.getRoot().toURI().toURL().toString()); profile.put(); DirectFileInputPreparator testee = new DirectFileInputPreparator(); ModelOutput<Text> output = testee.createOutput( new MockTextDefinition(), new MockInputDescription("base", "**/data-*.csv", format), profile.getTextContext()); put(output, "Hello, world!"); List<File> files = find("base"); assertThat(files.toString(), files.size(), is(1)); assertThat(get(files.get(0)), is(Arrays.asList("Hello, world!"))); } /** * configuration is not found. * @throws Exception if failed */ @Test(expected = IOException.class) public void no_config() throws Exception { DirectFileInputPreparator testee = new DirectFileInputPreparator(); testee.truncate( new MockInputDescription("base", "something", format), profile.getTextContext()); } /** * datasource is not found. * @throws Exception if failed */ @Test(expected = IOException.class) public void no_datasource() throws Exception { profile.add("root", HadoopDataSource.class, "other"); profile.add("root", HadoopDataSourceProfile.KEY_PATH, folder.getRoot().toURI().toURL().toString()); profile.put(); DirectFileInputPreparator testee = new DirectFileInputPreparator(); testee.truncate( new MockInputDescription("base", "something", format), profile.getTextContext()); } /** * using SPI. * @throws Exception if failed */ @Test public void spi() throws Exception { profile.add("root", HadoopDataSource.class, "/"); profile.add("root", HadoopDataSourceProfile.KEY_PATH, folder.getRoot().toURI().toURL().toString()); profile.put(); SpiImporterPreparator testee = new SpiImporterPreparator(getClass().getClassLoader()); ModelOutput<Text> output = testee.createOutput( new MockTextDefinition(), new MockInputDescription("base", "input.txt", format), profile.getTextContext()); put(output, "Hello, world!"); assertThat(get("base/input.txt"), is(Arrays.asList("Hello, world!"))); } private List<File> find(String targetPath) { List<File> results = new ArrayList<>(); LinkedList<File> work = new LinkedList<>(); work.add(new File(folder.getRoot(), targetPath)); while (work.isEmpty() == false) { File file = work.removeFirst(); if (file.getName().startsWith(".")) { continue; } if (file.isDirectory()) { Collections.addAll(work, file.listFiles()); } else { results.add(file); } } return results; } private List<String> get(String targetPath) throws IOException { return get(new File(folder.getRoot(), targetPath)); } private List<String> get(File target) throws FileNotFoundException { try (Scanner s = new Scanner(target, "UTF-8")) { List<String> results = new ArrayList<>(); while (s.hasNextLine()) { results.add(s.nextLine()); } return results; } } private void put(ModelOutput<Text> output, String... contents) throws IOException { try { Text text = new Text(); for (String line : contents) { text.set(line); output.write(text); } } finally { output.close(); } } private File put(String targetPath, String... contents) throws IOException { File target = new File(folder.getRoot(), targetPath); target.getParentFile().mkdirs(); try (PrintWriter w = new PrintWriter(target, "UTF-8")) { for (String line : contents) { w.println(line); } } return target; } }