/**
* Copyright 2011-2014 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.compiler.flow.plan;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.util.ArrayList;
import java.util.Arrays;
import org.junit.Test;
import com.asakusafw.compiler.flow.FlowGraphGenerator;
import com.asakusafw.vocabulary.flow.graph.FlowBoundary;
import com.asakusafw.vocabulary.flow.graph.FlowElement;
import com.asakusafw.vocabulary.flow.graph.FlowElementInput;
import com.asakusafw.vocabulary.flow.graph.FlowElementOutput;
import com.asakusafw.vocabulary.flow.graph.ObservationCount;
/**
* Test for {@link FlowBlock}.
*/
public class FlowBlockTest {
/**
* {@link FlowBlock#isEmpty()}
*/
@Test
public void isEmpty() {
FlowGraphGenerator gen = new FlowGraphGenerator();
gen.defineInput("in");
gen.defineOperator("op", "in", "out");
gen.defineOutput("out");
gen.connect("in", "op").connect("op", "out");
FlowBlock block = FlowBlock.fromPorts(
0,
gen.toGraph(),
new ArrayList<FlowElementInput>(gen.inputs()),
new ArrayList<FlowElementOutput>(gen.outputs()),
gen.getAsSet("op"));
assertThat(block.isEmpty(), is(true));
}
/**
* {@link FlowBlock#isEmpty()}
*/
@Test
public void isEmpty_input() {
FlowGraphGenerator gen = new FlowGraphGenerator();
gen.defineInput("in");
gen.defineOperator("op", "in", "out");
gen.defineOutput("out");
gen.connect("in", "op").connect("op", "out");
FlowBlock block = FlowBlock.fromPorts(
0,
gen.toGraph(),
new ArrayList<FlowElementInput>(gen.inputs("op")),
new ArrayList<FlowElementOutput>(gen.outputs()),
gen.getAsSet("op"));
assertThat(block.isEmpty(), is(false));
}
/**
* {@link FlowBlock#isEmpty()}
*/
@Test
public void isEmpty_output() {
FlowGraphGenerator gen = new FlowGraphGenerator();
gen.defineInput("in");
gen.defineOperator("op", "in", "out");
gen.defineOutput("out");
gen.connect("in", "op").connect("op", "out");
FlowBlock block = FlowBlock.fromPorts(
0,
gen.toGraph(),
new ArrayList<FlowElementInput>(gen.inputs()),
new ArrayList<FlowElementOutput>(gen.outputs("op")),
gen.getAsSet("op"));
assertThat(block.isEmpty(), is(false));
}
/**
* {@link FlowBlock#isReduceBlock()}
*/
@Test
public void isReduceBlock_true() {
FlowGraphGenerator gen = new FlowGraphGenerator();
gen.defineInput("in");
gen.defineOperator("op", "in", "out", FlowBoundary.SHUFFLE);
gen.defineOutput("out");
gen.connect("in", "op").connect("op", "out");
FlowBlock block = FlowBlock.fromPorts(
0,
gen.toGraph(),
new ArrayList<FlowElementInput>(gen.inputs("op")),
new ArrayList<FlowElementOutput>(gen.outputs("op")),
gen.getAsSet("op"));
assertThat(block.isReduceBlock(), is(true));
}
/**
* {@link FlowBlock#isReduceBlock()}
*/
@Test
public void isReduceBlock_false() {
FlowGraphGenerator gen = new FlowGraphGenerator();
gen.defineInput("in");
gen.defineOperator("op", "in", "out");
gen.defineOutput("out");
gen.connect("in", "op").connect("op", "out");
FlowBlock block = FlowBlock.fromPorts(
0,
gen.toGraph(),
new ArrayList<FlowElementInput>(gen.inputs("op")),
new ArrayList<FlowElementOutput>(gen.outputs("op")),
gen.getAsSet("op"));
assertThat(block.isReduceBlock(), is(false));
}
/**
* {@link FlowBlock#detach()}
*/
@Test
public void detach_1() {
FlowGraphGenerator gen = new FlowGraphGenerator();
gen.defineInput("in");
gen.defineOperator("op", "in", "out");
gen.defineOutput("out");
gen.connect("in", "op").connect("op", "out");
FlowBlock block = FlowBlock.fromPorts(
0,
gen.toGraph(),
new ArrayList<FlowElementInput>(gen.inputs("op")),
new ArrayList<FlowElementOutput>(gen.outputs("op")),
gen.getAsSet("op"));
block.detach();
assertThat(block.getElements().size(), is(1));
assertThat(block.getBlockInputs().size(), is(1));
assertThat(block.getBlockOutputs().size(), is(1));
FlowElement op = block.getElements().iterator().next();
FlowBlock.Input input = block.getBlockInputs().get(0);
FlowBlock.Output output = block.getBlockOutputs().get(0);
assertThat(op, not(sameInstance(gen.get("op"))));
assertThat(input.getElementPort(), not(sameInstance(gen.input("op"))));
assertThat(output.getElementPort(), not(sameInstance(gen.output("op"))));
assertThat(input.getElementPort().getOwner(), is(op));
assertThat(output.getElementPort().getOwner(), is(op));
assertThat(input.getConnections().isEmpty(), is(true));
assertThat(output.getConnections().isEmpty(), is(true));
}
/**
* {@link FlowBlock#detach()}
*/
@Test
public void detach_2() {
FlowGraphGenerator gen = new FlowGraphGenerator();
gen.defineInput("in");
gen.defineOperator("op1", "in", "out");
gen.defineOperator("op2", "in", "out");
gen.defineOutput("out");
gen.connect("in", "op1").connect("op1", "op2").connect("op2", "out");
FlowBlock block = FlowBlock.fromPorts(
0,
gen.toGraph(),
new ArrayList<FlowElementInput>(gen.inputs("op1")),
new ArrayList<FlowElementOutput>(gen.outputs("op2")),
gen.getAsSet("op1", "op2"));
block.detach();
assertThat(block.getElements().size(), is(2));
assertThat(block.getBlockInputs().size(), is(1));
assertThat(block.getBlockOutputs().size(), is(1));
FlowBlock.Input input = block.getBlockInputs().get(0);
FlowBlock.Output output = block.getBlockOutputs().get(0);
assertThat(input.getElementPort(), not(sameInstance(gen.input("op1"))));
assertThat(output.getElementPort(), not(sameInstance(gen.output("op2"))));
FlowElement op1 = input.getElementPort().getOwner();
FlowElement op2 = output.getElementPort().getOwner();
assertThat(op1.getInputPorts().get(0).getConnected().size(), is(0));
assertThat(op1.getOutputPorts().get(0).getConnected().size(), is(1));
assertThat(op2.getInputPorts().get(0).getConnected().size(), is(1));
assertThat(op2.getOutputPorts().get(0).getConnected().size(), is(0));
assertThat(op1.getOutputPorts().get(0).getConnected(),
is(op2.getInputPorts().get(0).getConnected()));
}
/**
* {@link FlowBlock#connect(FlowBlock.Output, FlowBlock.Input)}
*/
@Test
public void connect() {
FlowGraphGenerator gen = new FlowGraphGenerator();
gen.defineInput("in");
gen.defineOperator("op1", "in", "out");
gen.defineOperator("op2", "in", "out");
gen.defineOutput("out");
gen.connect("in", "op1").connect("op1", "op2").connect("op2", "out");
FlowBlock b1 = FlowBlock.fromPorts(
0,
gen.toGraph(),
new ArrayList<FlowElementInput>(gen.inputs("op1")),
new ArrayList<FlowElementOutput>(gen.outputs("op1")),
gen.getAsSet("op1"));
FlowBlock b2 = FlowBlock.fromPorts(
0,
gen.toGraph(),
new ArrayList<FlowElementInput>(gen.inputs("op2")),
new ArrayList<FlowElementOutput>(gen.outputs("op2")),
gen.getAsSet("op2"));
FlowBlock.connect(b1.getBlockOutputs().get(0), b2.getBlockInputs().get(0));
b1.detach();
b2.detach();
assertThat(b1.getBlockInputs().get(0).getConnections().size(), is(0));
assertThat(b2.getBlockInputs().get(0).getConnections().size(), is(1));
assertThat(b1.getBlockOutputs().get(0).getConnections().size(), is(1));
assertThat(b2.getBlockOutputs().get(0).getConnections().size(), is(0));
assertThat(b1.getBlockOutputs().get(0).getConnections().get(0).getUpstream(),
is(b1.getBlockOutputs().get(0)));
assertThat(b1.getBlockOutputs().get(0).getConnections().get(0).getDownstream(),
is(b2.getBlockInputs().get(0)));
assertThat(b2.getBlockInputs().get(0).getConnections().get(0).getDownstream(),
is(b2.getBlockInputs().get(0)));
assertThat(b2.getBlockInputs().get(0).getConnections().get(0).getUpstream(),
is(b1.getBlockOutputs().get(0)));
}
/**
* {@link FlowBlock#isSucceedingReduceBlock()}
*/
@Test
public void isSucceedingReduceBlock_true() {
FlowGraphGenerator gen = new FlowGraphGenerator();
gen.defineInput("in");
gen.defineOperator("op1", "in", "out");
gen.defineOperator("op2", "in", "out", FlowBoundary.SHUFFLE);
gen.defineOutput("out");
gen.connect("in", "op1").connect("op1", "op2").connect("op2", "out");
FlowBlock b1 = FlowBlock.fromPorts(
0,
gen.toGraph(),
new ArrayList<FlowElementInput>(gen.inputs("op1")),
new ArrayList<FlowElementOutput>(gen.outputs("op1")),
gen.getAsSet("op1"));
FlowBlock b2 = FlowBlock.fromPorts(
0,
gen.toGraph(),
new ArrayList<FlowElementInput>(gen.inputs("op2")),
new ArrayList<FlowElementOutput>(gen.outputs("op2")),
gen.getAsSet("op2"));
FlowBlock.connect(b1.getBlockOutputs().get(0), b2.getBlockInputs().get(0));
b1.detach();
b2.detach();
assertThat(b1.isSucceedingReduceBlock(), is(true));
}
/**
* {@link FlowBlock#isSucceedingReduceBlock()}
*/
@Test
public void isSucceedingReduceBlock_false() {
FlowGraphGenerator gen = new FlowGraphGenerator();
gen.defineInput("in");
gen.defineOperator("op1", "in", "out");
gen.defineOperator("op2", "in", "out");
gen.defineOutput("out");
gen.connect("in", "op1").connect("op1", "op2").connect("op2", "out");
FlowBlock b1 = FlowBlock.fromPorts(
0,
gen.toGraph(),
new ArrayList<FlowElementInput>(gen.inputs("op1")),
new ArrayList<FlowElementOutput>(gen.outputs("op1")),
gen.getAsSet("op1"));
FlowBlock b2 = FlowBlock.fromPorts(
0,
gen.toGraph(),
new ArrayList<FlowElementInput>(gen.inputs("op2")),
new ArrayList<FlowElementOutput>(gen.outputs("op2")),
gen.getAsSet("op2"));
FlowBlock.connect(b1.getBlockOutputs().get(0), b2.getBlockInputs().get(0));
b1.detach();
b2.detach();
assertThat(b1.isSucceedingReduceBlock(), is(false));
}
/**
* {@link FlowBlock#isSucceedingReduceBlock()}
*/
@Test
public void isSucceedingReduceBlock_empty() {
FlowGraphGenerator gen = new FlowGraphGenerator();
gen.defineInput("in");
gen.defineOperator("op1", "in", "out");
gen.defineOperator("op2", "in", "out", FlowBoundary.SHUFFLE);
gen.defineOutput("out");
gen.connect("in", "op1").connect("op1", "op2").connect("op2", "out");
FlowBlock b1 = FlowBlock.fromPorts(
0,
gen.toGraph(),
new ArrayList<FlowElementInput>(gen.inputs("op1")),
new ArrayList<FlowElementOutput>(gen.outputs("op1")),
gen.getAsSet("op1"));
FlowBlock b2 = FlowBlock.fromPorts(
0,
gen.toGraph(),
new ArrayList<FlowElementInput>(gen.inputs("op2")),
new ArrayList<FlowElementOutput>(gen.outputs("op2")),
gen.getAsSet("op2"));
b1.detach();
b2.detach();
assertThat(b1.isSucceedingReduceBlock(), is(false));
}
/**
* {@link FlowBlock#compaction()}
*/
@Test
public void compaction_deadIn() {
FlowGraphGenerator gen = new FlowGraphGenerator();
gen.defineInput("in1");
gen.defineInput("in2");
gen.defineOperator("op1", "in1 in2", "out1 out2");
gen.defineOutput("out1");
gen.defineOutput("out2");
gen.connect("in1", "op1.in1").connect("op1.out1", "out1");
gen.connect("in2", "op1.in2").connect("op1.out2", "out2");
FlowBlock bin = FlowBlock.fromPorts(
0,
gen.toGraph(),
new ArrayList<FlowElementInput>(gen.inputs()),
Arrays.asList(gen.output("in1"), gen.output("in2")),
gen.getAsSet("in1", "in2"));
FlowBlock b1 = FlowBlock.fromPorts(
0,
gen.toGraph(),
Arrays.asList(gen.input("op1.in1"), gen.input("op1.in2")),
Arrays.asList(gen.output("op1.out1"), gen.output("op1.out2")),
gen.getAsSet("op1"));
FlowBlock bout = FlowBlock.fromPorts(
0,
gen.toGraph(),
Arrays.asList(gen.input("out1"), gen.input("out2")),
new ArrayList<FlowElementOutput>(gen.outputs()),
gen.getAsSet("out1", "out2"));
FlowBlock.connect(bin.getBlockOutputs().get(0), b1.getBlockInputs().get(0));
FlowBlock.connect(b1.getBlockOutputs().get(0), bout.getBlockInputs().get(0));
FlowBlock.connect(b1.getBlockOutputs().get(1), bout.getBlockInputs().get(1));
bin.detach();
b1.detach();
bout.detach();
assertThat(b1.compaction(), is(true));
assertThat(b1.getBlockInputs().size(), is(1));
assertThat(b1.getBlockOutputs().size(), is(2));
assertThat(b1.getElements().size(), is(1));
assertThat(b1.getBlockInputs().get(0).getElementPort().getDescription().getName(),
is("in1"));
}
/**
* {@link FlowBlock#compaction()}
*/
@Test
public void compaction_deadOut() {
FlowGraphGenerator gen = new FlowGraphGenerator();
gen.defineInput("in1");
gen.defineInput("in2");
gen.defineOperator("op1", "in1 in2", "out1 out2");
gen.defineOutput("out1");
gen.defineOutput("out2");
gen.connect("in1", "op1.in1").connect("op1.out1", "out1");
gen.connect("in2", "op1.in2").connect("op1.out2", "out2");
FlowBlock bin = FlowBlock.fromPorts(
0,
gen.toGraph(),
new ArrayList<FlowElementInput>(gen.inputs()),
Arrays.asList(gen.output("in1"), gen.output("in2")),
gen.getAsSet("in1", "in2"));
FlowBlock b1 = FlowBlock.fromPorts(
0,
gen.toGraph(),
Arrays.asList(gen.input("op1.in1"), gen.input("op1.in2")),
Arrays.asList(gen.output("op1.out1"), gen.output("op1.out2")),
gen.getAsSet("op1"));
FlowBlock bout = FlowBlock.fromPorts(
0,
gen.toGraph(),
Arrays.asList(gen.input("out1"), gen.input("out2")),
new ArrayList<FlowElementOutput>(gen.outputs()),
gen.getAsSet("out1", "out2"));
FlowBlock.connect(bin.getBlockOutputs().get(0), b1.getBlockInputs().get(0));
FlowBlock.connect(bin.getBlockOutputs().get(1), b1.getBlockInputs().get(1));
FlowBlock.connect(b1.getBlockOutputs().get(0), bout.getBlockInputs().get(0));
bin.detach();
b1.detach();
bout.detach();
assertThat(b1.compaction(), is(true));
assertThat(b1.getBlockInputs().size(), is(2));
assertThat(b1.getBlockOutputs().size(), is(1));
assertThat(b1.getElements().size(), is(1));
assertThat(b1.getBlockOutputs().get(0).getElementPort().getDescription().getName(),
is("out1"));
}
/**
* {@link FlowBlock#compaction()}
*/
@Test
public void compaction_emptyIn() {
FlowGraphGenerator gen = new FlowGraphGenerator();
gen.defineInput("in1");
gen.defineOperator("op1", "in", "out");
gen.defineOperator("op2", "in", "out");
gen.defineOutput("out1");
gen.connect("in1", "op1").connect("op1", "op2").connect("op2", "out1");
FlowBlock bin = FlowBlock.fromPorts(
0,
gen.toGraph(),
new ArrayList<FlowElementInput>(gen.inputs()),
Arrays.asList(gen.output("in1")),
gen.getAsSet("in1"));
FlowBlock b1 = FlowBlock.fromPorts(
0,
gen.toGraph(),
Arrays.asList(gen.input("op1")),
Arrays.asList(gen.output("op2")),
gen.getAsSet("op1", "op2"));
FlowBlock bout = FlowBlock.fromPorts(
0,
gen.toGraph(),
Arrays.asList(gen.input("out1")),
new ArrayList<FlowElementOutput>(gen.outputs()),
gen.getAsSet("out1"));
FlowBlock.connect(b1.getBlockOutputs().get(0), bout.getBlockInputs().get(0));
bin.detach();
b1.detach();
bout.detach();
assertThat(b1.compaction(), is(true));
assertThat(b1.getBlockInputs().size(), is(0));
assertThat(b1.getBlockOutputs().size(), is(0));
assertThat(b1.getElements().size(), is(0));
}
/**
* {@link FlowBlock#compaction()}
*/
@Test
public void compaction_stopOut() {
FlowGraphGenerator gen = new FlowGraphGenerator();
gen.defineInput("in1");
gen.defineOperator("op1", "in", "out");
gen.defineOperator("op2", "in", "out");
gen.defineOutput("out1");
gen.connect("in1", "op1").connect("op1", "op2").connect("op2", "out1");
FlowBlock bin = FlowBlock.fromPorts(
0,
gen.toGraph(),
new ArrayList<FlowElementInput>(gen.inputs()),
Arrays.asList(gen.output("in1")),
gen.getAsSet("in1"));
FlowBlock b1 = FlowBlock.fromPorts(
0,
gen.toGraph(),
Arrays.asList(gen.input("op1")),
Arrays.asList(gen.output("op2")),
gen.getAsSet("op1", "op2"));
FlowBlock bout = FlowBlock.fromPorts(
0,
gen.toGraph(),
Arrays.asList(gen.input("out1")),
new ArrayList<FlowElementOutput>(gen.outputs()),
gen.getAsSet("out1"));
FlowBlock.connect(bin.getBlockOutputs().get(0), b1.getBlockInputs().get(0));
bin.detach();
b1.detach();
bout.detach();
assertThat(b1.compaction(), is(true));
assertThat(b1.getBlockInputs().size(), is(0));
assertThat(b1.getBlockOutputs().size(), is(0));
assertThat(b1.getElements().size(), is(0));
}
/**
* {@link FlowBlock#compaction()}
*/
@Test
public void compaction_mandatoryStop() {
FlowGraphGenerator gen = new FlowGraphGenerator();
gen.defineInput("in1");
gen.defineOperator("op1", "in", "out");
gen.defineOperator("op2", "in", "out", ObservationCount.AT_LEAST_ONCE);
gen.defineOutput("out1");
gen.connect("in1", "op1").connect("op1", "op2").connect("op2", "out1");
FlowBlock bin = FlowBlock.fromPorts(
0,
gen.toGraph(),
new ArrayList<FlowElementInput>(gen.inputs()),
Arrays.asList(gen.output("in1")),
gen.getAsSet("in1"));
FlowBlock b1 = FlowBlock.fromPorts(
0,
gen.toGraph(),
Arrays.asList(gen.input("op1")),
Arrays.asList(gen.output("op2")),
gen.getAsSet("op1", "op2"));
FlowBlock bout = FlowBlock.fromPorts(
0,
gen.toGraph(),
Arrays.asList(gen.input("out1")),
new ArrayList<FlowElementOutput>(gen.outputs()),
gen.getAsSet("out1"));
FlowBlock.connect(bin.getBlockOutputs().get(0), b1.getBlockInputs().get(0));
bin.detach();
b1.detach();
bout.detach();
assertThat(b1.compaction(), is(true));
assertThat(b1.getBlockInputs().size(), is(1));
assertThat(b1.getBlockOutputs().size(), is(0));
assertThat(b1.getElements().size(), is(2));
}
/**
* {@link FlowBlock#compaction()}
*/
@Test
public void compaction_stable() {
FlowGraphGenerator gen = new FlowGraphGenerator();
gen.defineInput("in1");
gen.defineOperator("op1", "in", "out");
gen.defineOperator("op2", "in", "out");
gen.defineOutput("out1");
gen.connect("in1", "op1").connect("op1", "op2").connect("op2", "out1");
FlowBlock bin = FlowBlock.fromPorts(
0,
gen.toGraph(),
new ArrayList<FlowElementInput>(gen.inputs()),
Arrays.asList(gen.output("in1")),
gen.getAsSet("in1"));
FlowBlock b1 = FlowBlock.fromPorts(
0,
gen.toGraph(),
Arrays.asList(gen.input("op1")),
Arrays.asList(gen.output("op2")),
gen.getAsSet("op1", "op2"));
FlowBlock bout = FlowBlock.fromPorts(
0,
gen.toGraph(),
Arrays.asList(gen.input("out1")),
new ArrayList<FlowElementOutput>(gen.outputs()),
gen.getAsSet("out1"));
FlowBlock.connect(b1.getBlockOutputs().get(0), bout.getBlockInputs().get(0));
FlowBlock.connect(bin.getBlockOutputs().get(0), b1.getBlockInputs().get(0));
bin.detach();
b1.detach();
bout.detach();
assertThat(b1.compaction(), is(false));
}
}