/** * 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.yaess.multidispatch; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Properties; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import com.asakusafw.yaess.core.CommandScript; import com.asakusafw.yaess.core.ExecutionContext; import com.asakusafw.yaess.core.ExecutionMonitor; import com.asakusafw.yaess.core.ExecutionPhase; import com.asakusafw.yaess.core.ExecutionScriptHandler; import com.asakusafw.yaess.core.ProfileContext; import com.asakusafw.yaess.core.ServiceProfile; import com.asakusafw.yaess.core.VariableResolver; import com.asakusafw.yaess.multidispatch.FailCommandScriptHandler.MessageException; /** * Test for {@link ExecutionScriptHandlerDispatcher}. */ public class ExecutionScriptHandlerDispatcherTest { private static final String BATCH_ID = "batch"; private static final String PREFIX = "testing"; /** * Temporary folder. */ @Rule public final TemporaryFolder folder = new TemporaryFolder(); /** * obtains handler ID. * @throws Exception if failed */ @Test public void getHandlerId() throws Exception { Map<String, String> conf = createConf(); declare(conf, "default", MockCommandScriptHandler.class); CommandScriptHandlerDispatcher dispatcher = create(conf); assertThat(dispatcher.getHandlerId(), is(PREFIX)); } /** * obtains resource ID. * @throws Exception if failed */ @Test public void getResourceId() throws Exception { put("testing.*=other"); Map<String, String> conf = createConf(); declare(conf, "default", MockCommandScriptHandler.class); declare(conf, "other", MockCommandScriptHandler.class); CommandScriptHandlerDispatcher dispatcher = create(conf); ExecutionContext something = context("something"); assertThat(dispatcher.getResourceId(something, null), is("default")); ExecutionContext testing = context("testing"); assertThat(dispatcher.getResourceId(testing, null), is("other")); } /** * obtains prop. * @throws Exception if failed */ @Test public void getProperties() throws Exception { put("testing.*=other"); Map<String, String> conf = createConf(); declare(conf, "default", MockCommandScriptHandler.class); declare(conf, "other", MockCommandScriptHandler.class); CommandScriptHandlerDispatcher dispatcher = create(conf); ExecutionContext something = context("something"); assertThat(dispatcher.getProperties(something, null).get("value"), is("default")); ExecutionContext testing = context("testing"); assertThat(dispatcher.getProperties(testing, null).get("value"), is("other")); } /** * obtains env. * @throws Exception if failed */ @Test public void getEnvironmentVariables() throws Exception { put("testing.*=other"); Map<String, String> conf = createConf(); declare(conf, "default", MockCommandScriptHandler.class); declare(conf, "other", MockCommandScriptHandler.class); CommandScriptHandlerDispatcher dispatcher = create(conf); ExecutionContext something = context("something"); assertThat(dispatcher.getEnvironmentVariables(something, null).get("value"), is("default")); ExecutionContext testing = context("testing"); assertThat(dispatcher.getEnvironmentVariables(testing, null).get("value"), is("other")); } /** * run setUp. * @throws Exception if failed */ @Test public void setUp() throws Exception { Map<String, String> conf = createConf(); declare(conf, "default", FailCommandScriptHandler.class); declare(conf, "other", FailCommandScriptHandler.class); declare(conf, "specified", FailCommandScriptHandler.class); CommandScriptHandlerDispatcher dispatcher = create(conf); ExecutionContext something = context("testing", ExecutionPhase.SETUP); try { dispatcher.setUp(ExecutionMonitor.NULL, something); fail(); } catch (MessageException e) { assertThat(e.message, is("default")); assertThat(e.context.getPhase(), is(ExecutionPhase.SETUP)); } } /** * run setUp. * @throws Exception if failed */ @Test public void setUp_match() throws Exception { put("testing.*=other"); Map<String, String> conf = createConf(); declare(conf, "default", FailCommandScriptHandler.class); declare(conf, "other", FailCommandScriptHandler.class); declare(conf, "specified", FailCommandScriptHandler.class); CommandScriptHandlerDispatcher dispatcher = create(conf); ExecutionContext something = context("testing", ExecutionPhase.SETUP); try { dispatcher.setUp(ExecutionMonitor.NULL, something); fail(); } catch (MessageException e) { assertThat(e.message, is("other")); assertThat(e.context.getPhase(), is(ExecutionPhase.SETUP)); } } /** * run setUp. * @throws Exception if failed */ @Test public void setUp_specified() throws Exception { put("testing.*=other"); Map<String, String> conf = createConf(); declare(conf, "default", FailCommandScriptHandler.class); declare(conf, "other", FailCommandScriptHandler.class); declare(conf, "specified", FailCommandScriptHandler.class); declare(conf, ExecutionScriptHandlerDispatcher.KEY_SETUP, "specified"); CommandScriptHandlerDispatcher dispatcher = create(conf); ExecutionContext something = context("testing", ExecutionPhase.SETUP); try { dispatcher.setUp(ExecutionMonitor.NULL, something); fail(); } catch (MessageException e) { assertThat(e.message, is("specified")); assertThat(e.context.getPhase(), is(ExecutionPhase.SETUP)); } } /** * runs execute. * @throws Exception if failed */ @Test public void execute() throws Exception { put("testing.*=other"); Map<String, String> conf = createConf(); declare(conf, "default", FailCommandScriptHandler.class); declare(conf, "other", FailCommandScriptHandler.class); CommandScriptHandlerDispatcher dispatcher = create(conf); CommandScript script = script("stage"); ExecutionContext something = context("something", ExecutionPhase.MAIN); try { dispatcher.execute(ExecutionMonitor.NULL, something, script); fail(); } catch (MessageException e) { assertThat(e.message, is("default")); assertThat(e.context.getPhase(), is(ExecutionPhase.MAIN)); } ExecutionContext testing = context("testing"); try { dispatcher.execute(ExecutionMonitor.NULL, testing, script); fail(); } catch (MessageException e) { assertThat(e.message, is("other")); assertThat(e.context.getPhase(), is(ExecutionPhase.MAIN)); } } /** * match to stage. * @throws Exception if failed */ @Test public void match_stage() throws Exception { put("flow.main.stage=match"); Map<String, String> conf = createConf(); declare(conf, "default", MockCommandScriptHandler.class); declare(conf, "match", MockCommandScriptHandler.class); CommandScriptHandlerDispatcher dispatcher = create(conf); ExecutionContext context = context("flow", ExecutionPhase.MAIN); CommandScript script = script("stage"); assertThat(dispatcher.getResourceId(context, script), is("match")); ExecutionContext otherFlow = context("otherflow", ExecutionPhase.MAIN); assertThat(dispatcher.getResourceId(otherFlow, script), is("default")); ExecutionContext otherPhase = context("flow", ExecutionPhase.PROLOGUE); assertThat(dispatcher.getResourceId(otherPhase, script), is("default")); CommandScript otherScript = script("otherstage"); assertThat(dispatcher.getResourceId(context, otherScript), is("default")); } /** * match to phase. * @throws Exception if failed */ @Test public void match_phase() throws Exception { put("flow.main.*=match"); Map<String, String> conf = createConf(); declare(conf, "default", MockCommandScriptHandler.class); declare(conf, "match", MockCommandScriptHandler.class); CommandScriptHandlerDispatcher dispatcher = create(conf); ExecutionContext context = context("flow", ExecutionPhase.MAIN); CommandScript script = script("stage"); assertThat(dispatcher.getResourceId(context, script), is("match")); ExecutionContext otherFlow = context("otherflow", ExecutionPhase.MAIN); assertThat(dispatcher.getResourceId(otherFlow, script), is("default")); ExecutionContext otherPhase = context("flow", ExecutionPhase.PROLOGUE); assertThat(dispatcher.getResourceId(otherPhase, script), is("default")); CommandScript otherScript = script("otherstage"); assertThat(dispatcher.getResourceId(context, otherScript), is("match")); } /** * match to flow. * @throws Exception if failed */ @Test public void match_flow() throws Exception { put("flow.*=match"); Map<String, String> conf = createConf(); declare(conf, "default", MockCommandScriptHandler.class); declare(conf, "match", MockCommandScriptHandler.class); CommandScriptHandlerDispatcher dispatcher = create(conf); ExecutionContext context = context("flow", ExecutionPhase.MAIN); CommandScript script = script("stage"); assertThat(dispatcher.getResourceId(context, script), is("match")); ExecutionContext otherFlow = context("otherflow", ExecutionPhase.MAIN); assertThat(dispatcher.getResourceId(otherFlow, script), is("default")); ExecutionContext otherPhase = context("flow", ExecutionPhase.PROLOGUE); assertThat(dispatcher.getResourceId(otherPhase, script), is("match")); CommandScript otherScript = script("otherstage"); assertThat(dispatcher.getResourceId(context, otherScript), is("match")); } /** * match to batch. * @throws Exception if failed */ @Test public void match_batch() throws Exception { put("*=match"); Map<String, String> conf = createConf(); declare(conf, "default", MockCommandScriptHandler.class); declare(conf, "match", MockCommandScriptHandler.class); CommandScriptHandlerDispatcher dispatcher = create(conf); ExecutionContext context = context("flow", ExecutionPhase.MAIN); CommandScript script = script("stage"); assertThat(dispatcher.getResourceId(context, script), is("match")); ExecutionContext otherFlow = context("otherflow", ExecutionPhase.MAIN); assertThat(dispatcher.getResourceId(otherFlow, script), is("match")); ExecutionContext otherPhase = context("flow", ExecutionPhase.PROLOGUE); assertThat(dispatcher.getResourceId(otherPhase, script), is("match")); CommandScript otherScript = script("otherstage"); assertThat(dispatcher.getResourceId(context, otherScript), is("match")); } /** * run cleanUp. * @throws Exception if failed */ @Test public void cleanUp() throws Exception { Map<String, String> conf = createConf(); declare(conf, "default", FailCommandScriptHandler.class); declare(conf, "other", FailCommandScriptHandler.class); declare(conf, "specified", FailCommandScriptHandler.class); CommandScriptHandlerDispatcher dispatcher = create(conf); ExecutionContext something = context("testing", ExecutionPhase.CLEANUP); try { dispatcher.cleanUp(ExecutionMonitor.NULL, something); fail(); } catch (MessageException e) { assertThat(e.message, is("default")); assertThat(e.context.getPhase(), is(ExecutionPhase.CLEANUP)); } } /** * run cleanUp. * @throws Exception if failed */ @Test public void cleanUp_match() throws Exception { put("testing.*=other"); Map<String, String> conf = createConf(); declare(conf, "default", FailCommandScriptHandler.class); declare(conf, "other", FailCommandScriptHandler.class); declare(conf, "specified", FailCommandScriptHandler.class); CommandScriptHandlerDispatcher dispatcher = create(conf); ExecutionContext something = context("testing", ExecutionPhase.CLEANUP); try { dispatcher.cleanUp(ExecutionMonitor.NULL, something); fail(); } catch (MessageException e) { assertThat(e.message, is("other")); assertThat(e.context.getPhase(), is(ExecutionPhase.CLEANUP)); } } /** * run cleanUp. * @throws Exception if failed */ @Test public void cleanUp_specified() throws Exception { put("testing.*=other"); Map<String, String> conf = createConf(); declare(conf, "default", FailCommandScriptHandler.class); declare(conf, "other", FailCommandScriptHandler.class); declare(conf, "specified", FailCommandScriptHandler.class); declare(conf, ExecutionScriptHandlerDispatcher.KEY_CLEANUP, "specified"); CommandScriptHandlerDispatcher dispatcher = create(conf); ExecutionContext something = context("testing", ExecutionPhase.CLEANUP); try { dispatcher.cleanUp(ExecutionMonitor.NULL, something); fail(); } catch (MessageException e) { assertThat(e.message, is("specified")); assertThat(e.context.getPhase(), is(ExecutionPhase.CLEANUP)); } } /** * obtains resource ID. * @throws Exception if failed */ @Test(expected = IOException.class) public void unknown_resource() throws Exception { put("testing.*=unknown"); Map<String, String> conf = createConf(); declare(conf, "default", MockCommandScriptHandler.class); declare(conf, "other", MockCommandScriptHandler.class); CommandScriptHandlerDispatcher dispatcher = create(conf); ExecutionContext testing = context("testing"); dispatcher.getResourceId(testing, null); } /** * conf directory is not defined. * @throws Exception if failed */ @Test(expected = IOException.class) public void missing_confdir() throws Exception { Map<String, String> conf = new HashMap<>(); declare(conf, "default", MockCommandScriptHandler.class); create(conf); } /** * setup target is wrong. * @throws Exception if failed */ @Test(expected = IOException.class) public void invalid_forceSetup() throws Exception { Map<String, String> conf = createConf(); declare(conf, ExecutionScriptHandlerDispatcher.KEY_SETUP, "INVALID"); declare(conf, "default", MockCommandScriptHandler.class); create(conf); } /** * setup target is wrong. * @throws Exception if failed */ @Test(expected = IOException.class) public void invalid_forceCleanup() throws Exception { Map<String, String> conf = createConf(); declare(conf, ExecutionScriptHandlerDispatcher.KEY_CLEANUP, "INVALID"); declare(conf, "default", MockCommandScriptHandler.class); create(conf); } /** * conf directory is invalid. * @throws Exception if failed */ @Test(expected = IOException.class) public void invalid_confdir() throws Exception { Map<String, String> conf = new HashMap<>(); conf.put(ExecutionScriptHandlerDispatcher.KEY_DIRECTORY, "${invalid}"); declare(conf, "default", MockCommandScriptHandler.class); create(conf); } /** * conf directory is not created. * @throws Exception if failed */ @Test public void confdir_not_exist() throws Exception { Map<String, String> conf = new HashMap<>(); conf.put(ExecutionScriptHandlerDispatcher.KEY_DIRECTORY, new File(folder.getRoot(), "empty").getAbsolutePath()); declare(conf, "default", MockCommandScriptHandler.class); CommandScriptHandlerDispatcher dispatcher = create(conf); assertThat(dispatcher.getResourceId(context("flow"), null), is("default")); } /** * obtains resource ID. * @throws Exception if failed */ @Test(expected = IOException.class) public void invalid_subcomponent() throws Exception { Map<String, String> conf = createConf(); declare(conf, "default", MockCommandScriptHandler.class); conf.put("invalid.subcomponent", "invalid"); create(conf); } /** * obtains resource ID. * @throws Exception if failed */ @Test(expected = IOException.class) public void missing_defaultcomponent() throws Exception { Map<String, String> conf = createConf(); declare(conf, "other", MockCommandScriptHandler.class); create(conf); } private CommandScriptHandlerDispatcher create(Map<String, String> conf) throws InterruptedException, IOException { ServiceProfile<CommandScriptHandlerDispatcher> profile = new ServiceProfile<>( PREFIX, CommandScriptHandlerDispatcher.class, conf, new ProfileContext( getClass().getClassLoader(), new VariableResolver(Collections.emptyMap()))); return profile.newInstance(); } private Map<String, String> createConf() { Map<String, String> conf = new HashMap<>(); conf.put(ExecutionScriptHandlerDispatcher.KEY_DIRECTORY, folder.getRoot().getAbsolutePath()); return conf; } private void declare(Map<String, String> conf, String key, String value) { conf.put(key, value); } private void declare(Map<String, String> conf, String name, Class<?> aClass) { conf.put(name, aClass.getName()); conf.put(name + "." + ExecutionScriptHandler.KEY_RESOURCE, name); conf.put(name + "." + ExecutionScriptHandler.KEY_ENV_PREFIX + "value", name); conf.put(name + "." + ExecutionScriptHandler.KEY_PROP_PREFIX + "value", name); } private void put(String... pairs) throws IOException { Properties p = new Properties(); for (String pair : pairs) { String[] atoms = pair.split("=", 2); p.setProperty(atoms[0], atoms[1]); } File file = folder.newFile(BATCH_ID + ExecutionScriptHandlerDispatcher.SUFFIX_CONF); try (OutputStream output = new FileOutputStream(file)) { p.store(output, BATCH_ID); } } private ExecutionContext context(String flowId) { return context(flowId, ExecutionPhase.MAIN); } private ExecutionContext context(String flowId, ExecutionPhase phase) { return new ExecutionContext(BATCH_ID, flowId, "exec", phase, Collections.emptyMap()); } CommandScript script(String scriptId) { CommandScript script = new CommandScript( scriptId, Collections.emptySet(), "profile", "module", Collections.singletonList("hello"), Collections.emptyMap()); return script; } }