Package com.asakusafw.compiler.flow.plan

Source Code of com.asakusafw.compiler.flow.plan.StagePlannerTest

/**
* 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.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

import com.asakusafw.compiler.flow.FlowCompilerOptions;
import com.asakusafw.compiler.flow.FlowCompilerOptions.GenericOptionValue;
import com.asakusafw.compiler.flow.FlowGraphGenerator;
import com.asakusafw.compiler.flow.FlowGraphRewriter;
import com.asakusafw.vocabulary.flow.graph.Connectivity;
import com.asakusafw.vocabulary.flow.graph.FlowBoundary;
import com.asakusafw.vocabulary.flow.graph.FlowElement;
import com.asakusafw.vocabulary.flow.graph.FlowElementKind;
import com.asakusafw.vocabulary.flow.graph.FlowGraph;

/**
* Test for {@link StagePlanner}.
*/
@RunWith(Parameterized.class)
public class StagePlannerTest {

    private final FlowGraphGenerator gen = new FlowGraphGenerator();

    private final GenericOptionValue opt;

    /**
     * Returns test parameter sets.
     * @return test parameter sets
     */
    @Parameters
    public static List<Object[]> parameters() {
        return Arrays.asList(new Object[][] {
                { GenericOptionValue.DISABLED },
                { GenericOptionValue.ENABLED },
        });
    }

    /**
     * Creates a new instance.
     * @param opt options
     */
    public StagePlannerTest(GenericOptionValue opt) {
        this.opt = opt;
    }

    private StagePlanner getPlanner() {
        FlowCompilerOptions options = new FlowCompilerOptions();
        options.setCompressConcurrentStage(false);
        options.setCompressFlowPart(false);
        options.setEnableCombiner(false);
        options.setEnableDebugLogging(true);
        options.setHashJoinForSmall(false);
        options.setHashJoinForTiny(false);
        options.putExtraAttribute(StagePlanner.KEY_COMPRESS_FLOW_BLOCK_GROUP, opt.getSymbol());
        return new StagePlanner(
                Collections.<FlowGraphRewriter>emptyList(),
                options);
        }

    /**
     * {@link StagePlanner#validate(FlowGraph)}
     */
    @Test
    public void validate_ok() {
        gen.defineInput("in");
        gen.defineOperator("op", "in", "out");
        gen.defineOutput("out");
        gen.connect("in", "op.in").connect("op.out", "out");

        FlowGraph graph = gen.toGraph();
        assertThat(getPlanner().validate(graph), is(true));
    }

    /**
     * {@link StagePlanner#validate(FlowGraph)}
     */
    @Test
    public void validate_notInConnected() {
        gen.defineInput("in");
        gen.defineOperator("op", "in opened", "out");
        gen.defineOutput("out");
        gen.connect("in", "op.in").connect("op.out", "out");

        FlowGraph graph = gen.toGraph();
        assertThat(getPlanner().validate(graph), is(false));
    }

    /**
     * {@link StagePlanner#validate(FlowGraph)}
     */
    @Test
    public void validate_notOutConnected() {
        gen.defineInput("in");
        gen.defineOperator("op", "in", "out opened");
        gen.defineOutput("out");
        gen.connect("in", "op.in").connect("op.out", "out");

        FlowGraph graph = gen.toGraph();
        assertThat(getPlanner().validate(graph), is(false));
    }

    /**
     * {@link StagePlanner#validate(FlowGraph)}
     */
    @Test
    public void validate_notOutConnected_butOptional() {
        gen.defineInput("in");
        gen.defineOperator("op", "in", "out opened", Connectivity.OPTIONAL);
        gen.defineOutput("out");
        gen.connect("in", "op.in").connect("op.out", "out");

        FlowGraph graph = gen.toGraph();
        assertThat(getPlanner().validate(graph), is(true));
    }

    /**
     * {@link StagePlanner#validate(FlowGraph)}
     */
    @Test
    public void validate_looped() {
        gen.defineInput("in");
        gen.defineOperator("op", "in", "out");
        gen.defineOperator("back", "in", "out");
        gen.defineOutput("out");
        gen.connect("in", "op.in").connect("op.out", "out");
        gen.connect("op", "back").connect("back", "op");

        FlowGraph graph = gen.toGraph();
        assertThat(getPlanner().validate(graph), is(false));
    }

    /**
     * {@link StagePlanner#validate(FlowGraph)}
     */
    @Test
    public void validate_componentError() {
        FlowGraphGenerator comp = new FlowGraphGenerator();
        comp.defineInput("in");
        comp.defineOperator("op", "in", "out opened");
        comp.defineOutput("out");
        comp.connect("in", "op.in").connect("op.out", "out");


        gen.defineInput("in");
        gen.defineFlowPart("c", comp.toGraph());
        gen.defineOutput("out");
        gen.connect("in", "c.in").connect("c.out", "out");

        FlowGraph graph = gen.toGraph();
        assertThat(getPlanner().validate(graph), is(false));
    }

    /**
     * {@link StagePlanner#insertCheckpoints(FlowGraph)}
     */
    @Test
    public void insertCheckpoints_insert() {
        gen.defineInput("in1");
        gen.defineOperator("op1", "in", "a b", FlowBoundary.SHUFFLE);
        gen.defineOperator("op2", "in", "out", FlowBoundary.SHUFFLE);
        gen.defineOutput("out1");
        gen.defineOutput("out2");
        gen.connect("in1", "op1").connect("op1.a", "op2").connect("op2", "out1");
        gen.connect("op1.b", "out2");

        FlowGraph graph = gen.toGraph();
        getPlanner().insertCheckpoints(graph);
        assertThat(FlowGraphUtil.collectBoundaries(graph),
                not(gen.getAsSet("in1", "op1", "op2", "out1", "out2")));

        Set<FlowElement> a = FlowGraphUtil.getSucceedingBoundaries(gen.output("op1.a"));
        Set<FlowElement> b = FlowGraphUtil.getSucceedingBoundaries(gen.output("op1.b"));
        assertThat(a.isEmpty(), is(false));
        assertThat(b.isEmpty(), is(false));

        for (FlowElement elem : a) {
            assertThat(FlowGraphUtil.isStageBoundary(elem), is(true));
        }
        for (FlowElement elem : b) {
            assertThat(FlowGraphUtil.isStageBoundary(elem), is(true));
        }
    }

    /**
     * {@link StagePlanner#insertCheckpoints(FlowGraph)}
     */
    @Test
    public void insertCheckpoints_nothing() {
        gen.defineInput("in1");
        gen.defineOperator("op1", "in", "a b", FlowBoundary.SHUFFLE);
        gen.defineOperator("op2", "in", "out");
        gen.defineOutput("out1");
        gen.defineOutput("out2");
        gen.connect("in1", "op1").connect("op1.a", "op2").connect("op2", "out1");
        gen.connect("op1.b", "out2");

        FlowGraph graph = gen.toGraph();
        getPlanner().insertCheckpoints(graph);

        assertThat(FlowGraphUtil.collectBoundaries(graph),
                is(gen.getAsSet("in1", "op1", "out1", "out2")));
    }

    /**
     * {@link StagePlanner#insertIdentities(FlowGraph)}
     */
    @Test
    public void insertIdentities_nothing() {
        gen.defineInput("in");
        gen.defineOperator("op", "in", "out");
        gen.defineOutput("out");
        gen.connect("in", "op.in").connect("op.out", "out");
        FlowGraph graph = gen.toGraph();
        getPlanner().insertIdentities(graph);

        assertThat(FlowGraphUtil.collectElements(graph),
                is(gen.getAsSet("in", "op", "out")));
    }

    /**
     * {@link StagePlanner#insertIdentities(FlowGraph)}
     */
    @Test
    public void insertIdentities_stage_shuffle() {
        gen.defineInput("in");
        gen.defineOperator("op1", "in", "out", FlowBoundary.SHUFFLE);
        gen.defineOperator("op2", "in", "out");
        gen.defineOutput("out");
        gen.connect("in", "op1").connect("op1", "op2").connect("op2", "out");
        FlowGraph graph = gen.toGraph();
        getPlanner().insertIdentities(graph);

        assertThat(FlowGraphUtil.collectElements(graph),
                not(gen.getAsSet("in", "op1", "op2", "out")));

        FlowElement id = succ(gen.get("in"));
        assertThat(FlowGraphUtil.isIdentity(id), is(true));

        FlowElement op1 = succ(id);
        assertThat(op1, is(gen.get("op1")));

        FlowElement op2 = succ(op1);
        assertThat(op2, is(gen.get("op2")));

        FlowElement out = succ(op2);
        assertThat(out, is(gen.get("out")));
    }

    /**
     * {@link StagePlanner#insertIdentities(FlowGraph)}
     */
    @Test
    public void insertIdentities_stage_stage() {
        gen.defineInput("in");
        gen.defineOperator("op1", "in", "out", FlowBoundary.STAGE);
        gen.defineOperator("op2", "in", "out");
        gen.defineOutput("out");
        gen.connect("in", "op1").connect("op1", "op2").connect("op2", "out");
        FlowGraph graph = gen.toGraph();
        getPlanner().insertIdentities(graph);

        assertThat(FlowGraphUtil.collectElements(graph),
                not(gen.getAsSet("in", "op1", "op2", "out")));

        FlowElement id = succ(gen.get("in"));
        assertThat(FlowGraphUtil.isIdentity(id), is(true));

        FlowElement op1 = succ(id);
        assertThat(op1, is(gen.get("op1")));

        FlowElement op2 = succ(op1);
        assertThat(op2, is(gen.get("op2")));

        FlowElement out = succ(op2);
        assertThat(out, is(gen.get("out")));
    }

    /**
     * {@link StagePlanner#insertIdentities(FlowGraph)}
     */
    @Test
    public void insertIdentities_shuffle_stage() {
        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");
        FlowGraph graph = gen.toGraph();
        getPlanner().insertIdentities(graph);

        assertThat(FlowGraphUtil.collectElements(graph),
                is(gen.getAsSet("in", "op1", "op2", "out")));
    }

    /**
     * {@link StagePlanner#splitIdentities(FlowGraph)}
     */
    @Test
    public void splitIdentities_nothing() {
        gen.defineInput("in");
        gen.defineOperator("op", "in", "out");
        gen.defineOutput("out");
        gen.connect("in", "op.in").connect("op.out", "out");

        FlowGraph graph = gen.toGraph();
        getPlanner().splitIdentities(graph);

        assertThat(FlowGraphUtil.collectElements(graph),
                is(gen.getAsSet("in", "op", "out")));
    }

    /**
     * {@link StagePlanner#splitIdentities(FlowGraph)}
     */
    @Test
    public void splitIdentities_split() {
        gen.defineInput("in1");
        gen.defineInput("in2");
        gen.definePseud("id");
        gen.defineOutput("out1");
        gen.defineOutput("out2");
        gen.connect("in1", "id").connect("id", "out1");
        gen.connect("in2", "id").connect("id", "out2");

        FlowGraph graph = gen.toGraph();
        getPlanner().splitIdentities(graph);

        Set<FlowElement> succ1 = FlowGraphUtil.getSuccessors(gen.get("in1"));
        Set<FlowElement> succ2 = FlowGraphUtil.getSuccessors(gen.get("in2"));

        assertThat(succ1.size(), is(2));
        assertThat(succ2.size(), is(2));

        Iterator<FlowElement> iter1 = succ1.iterator();
        FlowElement elem1 = iter1.next();
        FlowElement elem2 = iter1.next();
        Iterator<FlowElement> iter2 = succ2.iterator();
        FlowElement elem3 = iter2.next();
        FlowElement elem4 = iter2.next();

        assertThat(FlowGraphUtil.getSuccessors(elem1).size(), is(1));
        assertThat(FlowGraphUtil.getSuccessors(elem2).size(), is(1));
        assertThat(FlowGraphUtil.getSuccessors(elem3).size(), is(1));
        assertThat(FlowGraphUtil.getSuccessors(elem4).size(), is(1));
        assertThat(FlowGraphUtil.getPredecessors(elem1).size(), is(1));
        assertThat(FlowGraphUtil.getPredecessors(elem2).size(), is(1));
        assertThat(FlowGraphUtil.getPredecessors(elem3).size(), is(1));
        assertThat(FlowGraphUtil.getPredecessors(elem4).size(), is(1));

        assertThat(elem1, not(sameInstance(elem3)));
        assertThat(elem1, not(sameInstance(elem4)));
        assertThat(elem2, not(sameInstance(elem3)));
        assertThat(elem2, not(sameInstance(elem4)));
    }

    /**
     * {@link StagePlanner#splitIdentities(FlowGraph)}
     */
    @Test
    public void splitIdentities_yetSplitted() {
        gen.defineInput("in1");
        gen.definePseud("id1");
        gen.definePseud("id2");
        gen.defineOutput("out1");
        gen.defineOutput("out2");
        gen.connect("in1", "id1").connect("id1", "out1");
        gen.connect("in1", "id2").connect("id2", "out2");

        FlowGraph graph = gen.toGraph();
        getPlanner().splitIdentities(graph);

        assertThat(FlowGraphUtil.collectElements(graph),
                is(gen.getAsSet("in1", "id1", "id2", "out1", "out2")));
    }

    /**
     * {@link StagePlanner#reduceIdentities(FlowGraph)}
     */
    @Test
    public void reduceIdentities_op_op() {
        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");

        FlowGraph graph = gen.toGraph();
        getPlanner().reduceIdentities(graph);

        assertThat(FlowGraphUtil.collectElements(graph),
                is(gen.getAsSet("in", "op1", "op2", "out")));
        assertThat(succ(gen.get("in")), is(gen.get("op1")));
        assertThat(succ(gen.get("op1")), is(gen.get("op2")));
        assertThat(succ(gen.get("op2")), is(gen.get("out")));
    }

    /**
     * {@link StagePlanner#reduceIdentities(FlowGraph)}
     */
    @Test
    public void reduceIdentities_op_id() {
        gen.defineInput("in");
        gen.defineOperator("op1", "in", "out");
        gen.definePseud("id");
        gen.defineOutput("out");
        gen.connect("in", "op1").connect("op1", "id").connect("id", "out");

        FlowGraph graph = gen.toGraph();
        getPlanner().reduceIdentities(graph);

        assertThat(FlowGraphUtil.collectElements(graph),
                is(gen.getAsSet("in", "op1", "out")));

        assertThat(succ(gen.get("in")), is(gen.get("op1")));
        assertThat(succ(gen.get("op1")), is(gen.get("out")));
    }

    /**
     * {@link StagePlanner#reduceIdentities(FlowGraph)}
     */
    @Test
    public void reduceIdentities_id_op() {
        gen.defineInput("in");
        gen.definePseud("id");
        gen.defineOperator("op1", "in", "out");
        gen.defineOutput("out");
        gen.connect("in", "id").connect("id", "op1").connect("op1", "out");

        FlowGraph graph = gen.toGraph();
        getPlanner().reduceIdentities(graph);

        assertThat(FlowGraphUtil.collectElements(graph),
                is(gen.getAsSet("in", "op1", "out")));

        assertThat(succ(gen.get("in")), is(gen.get("op1")));
        assertThat(succ(gen.get("op1")), is(gen.get("out")));
    }

    /**
     * {@link StagePlanner#reduceIdentities(FlowGraph)}
     */
    @Test
    public void reduceIdentities_mapBody() {
        gen.defineInput("in");
        gen.definePseud("id");
        gen.defineOutput("out");
        gen.connect("in", "id").connect("id", "out");

        FlowGraph graph = gen.toGraph();
        getPlanner().reduceIdentities(graph);

        assertThat(FlowGraphUtil.collectElements(graph),
                is(gen.getAsSet("in", "id", "out")));

        assertThat(succ(gen.get("in")), is(gen.get("id")));
        assertThat(succ(gen.get("id")), is(gen.get("out")));
    }

    /**
     * {@link StagePlanner#reduceIdentities(FlowGraph)}
     */
    @Test
    public void reduceIdentities_reduceBody() {
        gen.defineInput("in");
        gen.defineOperator("op1", "in", "out", FlowBoundary.SHUFFLE);
        gen.definePseud("id");
        gen.defineOutput("out");
        gen.connect("in", "op1").connect("op1", "id").connect("id", "out");

        FlowGraph graph = gen.toGraph();
        getPlanner().reduceIdentities(graph);

        assertThat(FlowGraphUtil.collectElements(graph),
                is(gen.getAsSet("in", "op1", "out")));

        assertThat(succ(gen.get("in")), is(gen.get("op1")));
        assertThat(succ(gen.get("op1")), is(gen.get("out")));
    }

    /**
     * {@link StagePlanner#normalizeFlowGraph(FlowGraph)}
     */
    @Test
    public void normalizeFlowGraph() {
        gen.defineInput("in");
        gen.defineOperator("op1", "in", "out");
        gen.definePseud("id");
        gen.defineOutput("out1");
        gen.defineOutput("out2");
        gen.connect("in", "op1").connect("op1", "id").connect("id", "out1");
        gen.connect("id", "out2");

        FlowGraph graph = gen.toGraph();
        getPlanner().normalizeFlowGraph(graph);

        assertThat(FlowGraphUtil.collectElements(graph),
                is(gen.getAsSet("in", "op1", "out1", "out2")));

        assertThat(succ(gen.get("in")), is(gen.get("op1")));
        assertThat(FlowGraphUtil.getSuccessors(gen.get("op1")), is(gen.getAsSet("out1", "out2")));
        assertThat(pred(gen.get("out1")), is(gen.get("op1")));
        assertThat(pred(gen.get("out2")), is(gen.get("op1")));
        assertThat(pred(gen.get("op1")), is(gen.get("in")));
    }

    /**
     * {@link StagePlanner#normalizeFlowGraph(FlowGraph)}
     */
    @Test
    public void normalizeFlowGraph_component() {
        FlowGraphGenerator comp = new FlowGraphGenerator();
        comp.defineInput("in");
        comp.defineOperator("op1", "in", "out");
        comp.definePseud("id");
        comp.defineOutput("out1");
        comp.defineOutput("out2");
        comp.connect("in", "op1").connect("op1", "id").connect("id", "out1");
        comp.connect("id", "out2");

        gen.defineInput("in");
        gen.defineFlowPart("c", comp.toGraph());
        gen.defineOutput("out");
        gen.connect("in", "c").connect("c.out1", "out").connect("c.out2", "out");

        FlowGraph graph = gen.toGraph();
        getPlanner().normalizeFlowGraph(graph);
        deletePseuds(graph);

        assertThat(succ(gen.get("in")), is(comp.get("op1")));
        assertThat(succ(comp.get("op1")), is(gen.get("out")));
        assertThat(pred(gen.get("out")), is(comp.get("op1")));
        assertThat(pred(comp.get("op1")), is(gen.get("in")));
    }

    /**
     * {@link StagePlanner#plan(FlowGraph)}
     */
    @Test
    public void plan_through() {
        gen.defineInput("in");
        gen.defineOutput("out");
        gen.connect("in", "out");

        StageGraph stages = getPlanner().plan(gen.toGraph());

        assertThat(stages.getInput().getBlockOutputs().size(), is(1));
        assertThat(stages.getOutput().getBlockInputs().size(), is(1));
        assertThat(stages.getStages().size(), is(0));

        assertThat(FlowBlock.isConnected(
                stages.getInput().getBlockOutputs().get(0),
                stages.getOutput().getBlockInputs().get(0)), is(true));
    }

    /**
     * {@link StagePlanner#plan(FlowGraph)}
     */
    @Test
    public void plan_singleMapper() {
        gen.defineInput("in");
        gen.defineOperator("op", "in", "out");
        gen.defineOutput("out");
        gen.connect("in", "op").connect("op", "out");

        StageGraph stages = getPlanner().plan(gen.toGraph());

        assertThat(stages.getInput().getBlockOutputs().size(), is(1));
        assertThat(stages.getOutput().getBlockInputs().size(), is(1));
        assertThat(stages.getStages().size(), is(1));

        StageBlock mr = stages.getStages().get(0);
        assertThat(mr.getMapBlocks().size(), is(1));
        assertThat(mr.hasReduceBlocks(), is(false));

        FlowBlock mapper = single(mr.getMapBlocks());

        assertThat(FlowBlock.isConnected(
                stages.getInput().getBlockOutputs().get(0),
                mapper.getBlockInputs().get(0)), is(true));
        assertThat(FlowBlock.isConnected(
                mapper.getBlockOutputs().get(0),
                stages.getOutput().getBlockInputs().get(0)), is(true));

        assertThat(mapper.getElements().size(), is(1));
        FlowElement mapperOp = single(mapper.getElements());

        assertThat(mapperOp.getDescription(), is(gen.desc("op")));
    }

    /**
     * {@link StagePlanner#plan(FlowGraph)}
     */
    @Test
    public void plan_singleReducer() {
        gen.defineInput("in");
        gen.defineOperator("op", "in", "out", FlowBoundary.SHUFFLE);
        gen.defineOutput("out");
        gen.connect("in", "op").connect("op", "out");

        StageGraph stages = getPlanner().plan(gen.toGraph());

        assertThat(stages.getInput().getBlockOutputs().size(), is(1));
        assertThat(stages.getOutput().getBlockInputs().size(), is(1));
        assertThat(stages.getStages().size(), is(1));

        StageBlock mr = stages.getStages().get(0);
        assertThat(mr.getMapBlocks().size(), is(1));
        assertThat(mr.getReduceBlocks().isEmpty(), is(false));

        FlowBlock mapper = single(mr.getMapBlocks());
        FlowBlock reducer = single(mr.getReduceBlocks());

        assertThat(FlowBlock.isConnected(
                stages.getInput().getBlockOutputs().get(0),
                mapper.getBlockInputs().get(0)), is(true));
        assertThat(FlowBlock.isConnected(
                mapper.getBlockOutputs().get(0),
                reducer.getBlockInputs().get(0)), is(true));
        assertThat(FlowBlock.isConnected(
                reducer.getBlockOutputs().get(0),
                stages.getOutput().getBlockInputs().get(0)), is(true));

        assertThat(mapper.getElements().size(), is(1));
        FlowElement mapperOp = single(mapper.getElements());
        assertThat(FlowGraphUtil.isIdentity(mapperOp), is(true));

        assertThat(reducer.getElements().size(), is(1));
        FlowElement reducerOp = single(reducer.getElements());
        assertThat(reducerOp.getDescription(), is(gen.desc("op")));
    }

    /**
     * {@link StagePlanner#plan(FlowGraph)}
     */
    @Test
    public void plan_singleMapReduce() {
        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");

        StageGraph stages = getPlanner().plan(gen.toGraph());

        assertThat(stages.getInput().getBlockOutputs().size(), is(1));
        assertThat(stages.getOutput().getBlockInputs().size(), is(1));
        assertThat(stages.getStages().size(), is(1));

        StageBlock mr = stages.getStages().get(0);
        assertThat(mr.getMapBlocks().size(), is(1));
        assertThat(mr.getReduceBlocks().isEmpty(), is(false));

        FlowBlock mapper = single(mr.getMapBlocks());
        FlowBlock reducer = single(mr.getReduceBlocks());

        assertThat(FlowBlock.isConnected(
                stages.getInput().getBlockOutputs().get(0),
                mapper.getBlockInputs().get(0)), is(true));
        assertThat(FlowBlock.isConnected(
                mapper.getBlockOutputs().get(0),
                reducer.getBlockInputs().get(0)), is(true));
        assertThat(FlowBlock.isConnected(
                reducer.getBlockOutputs().get(0),
                stages.getOutput().getBlockInputs().get(0)), is(true));

        assertThat(mapper.getElements().size(), is(1));
        FlowElement mapperOp = single(mapper.getElements());
        assertThat(mapperOp.getDescription(), is(gen.desc("op1")));

        assertThat(reducer.getElements().size(), is(1));
        FlowElement reducerOp = single(reducer.getElements());
        assertThat(reducerOp.getDescription(), is(gen.desc("op2")));
    }

    /**
     * {@link StagePlanner#plan(FlowGraph)}
     */
    @Test
    public void plan_flowpart() {
        FlowGraphGenerator comp = new FlowGraphGenerator();
        comp.defineInput("in");
        comp.defineOperator("op1", "in", "out");
        comp.defineOperator("op2", "in", "out", FlowBoundary.SHUFFLE);
        comp.defineOutput("out");
        comp.connect("in", "op1").connect("op1", "op2").connect("op2", "out");

        gen.defineInput("in");
        gen.defineFlowPart("c", comp.toGraph());
        gen.defineOutput("out");
        gen.connect("in", "c").connect("c", "out");

        StageGraph stages = getPlanner().plan(gen.toGraph());

        assertThat(stages.getInput().getBlockOutputs().size(), is(1));
        assertThat(stages.getOutput().getBlockInputs().size(), is(1));
        assertThat(stages.getStages().size(), is(1));

        StageBlock mr = stages.getStages().get(0);
        assertThat(mr.getMapBlocks().size(), is(1));
        assertThat(mr.getReduceBlocks().isEmpty(), is(false));

        FlowBlock mapper = single(mr.getMapBlocks());
        FlowBlock reducer = single(mr.getReduceBlocks());

        assertThat(FlowBlock.isConnected(
                stages.getInput().getBlockOutputs().get(0),
                mapper.getBlockInputs().get(0)), is(true));
        assertThat(FlowBlock.isConnected(
                mapper.getBlockOutputs().get(0),
                reducer.getBlockInputs().get(0)), is(true));
        assertThat(FlowBlock.isConnected(
                reducer.getBlockOutputs().get(0),
                stages.getOutput().getBlockInputs().get(0)), is(true));

        assertThat(mapper.getElements().size(), is(1));
        FlowElement mapperOp = single(mapper.getElements());
        assertThat(mapperOp.getDescription(), is(comp.desc("op1")));

        assertThat(reducer.getElements().size(), is(1));
        FlowElement reducerOp = single(reducer.getElements());
        assertThat(reducerOp.getDescription(), is(comp.desc("op2")));
    }

    /**
     * {@link StagePlanner#plan(FlowGraph)}
     */
    @Test
    public void plan_flowpart_nested() {
        FlowGraphGenerator fp2 = new FlowGraphGenerator();
        fp2.defineInput("in");
        fp2.defineOperator("op1", "in", "out");
        fp2.defineOutput("out");
        fp2.connect("in", "op1").connect("op1", "out");

        FlowGraphGenerator fp1 = new FlowGraphGenerator();
        fp1.defineInput("in");
        fp1.defineFlowPart("fp2", fp2.toGraph());
        fp1.defineOutput("out");
        fp1.connect("in", "fp2").connect("fp2", "out");

        gen.defineInput("in");
        gen.defineFlowPart("fp1", fp1.toGraph());
        gen.defineOutput("out");
        gen.connect("in", "fp1").connect("fp1", "out");

        StageGraph stages = getPlanner().plan(gen.toGraph());

        assertThat(stages.getInput().getBlockOutputs().size(), is(1));
        assertThat(stages.getOutput().getBlockInputs().size(), is(1));
        assertThat(stages.getStages().size(), is(1));

        StageBlock mr = stages.getStages().get(0);
        assertThat(mr.getMapBlocks().size(), is(1));
        assertThat(mr.getReduceBlocks().isEmpty(), is(true));

        FlowBlock mapper = single(mr.getMapBlocks());

        assertThat(FlowBlock.isConnected(
                stages.getInput().getBlockOutputs().get(0),
                mapper.getBlockInputs().get(0)), is(true));
        assertThat(FlowBlock.isConnected(
                mapper.getBlockOutputs().get(0),
                stages.getOutput().getBlockInputs().get(0)), is(true));

        assertThat(mapper.getElements().size(), is(1));
        FlowElement mapperOp = single(mapper.getElements());
        assertThat(mapperOp.getDescription(), is(fp2.desc("op1")));
    }

    /**
     * {@link StagePlanner#plan(FlowGraph)}
     */
    @Test
    public void plan_flowpart_deep() {
        FlowGraphGenerator fp4 = new FlowGraphGenerator();
        fp4.defineInput("in");
        fp4.defineOperator("op1", "in", "out");
        fp4.defineOutput("out");
        fp4.connect("in", "op1").connect("op1", "out");

        FlowGraphGenerator fp3 = new FlowGraphGenerator();
        fp3.defineInput("in");
        fp3.defineFlowPart("fp4", fp4.toGraph());
        fp3.defineOutput("out");
        fp3.connect("in", "fp4").connect("fp4", "out");

        FlowGraphGenerator fp2 = new FlowGraphGenerator();
        fp2.defineInput("in");
        fp2.defineFlowPart("fp3", fp3.toGraph());
        fp2.defineOutput("out");
        fp2.connect("in", "fp3").connect("fp3", "out");

        FlowGraphGenerator fp1 = new FlowGraphGenerator();
        fp1.defineInput("in");
        fp1.defineFlowPart("fp2", fp2.toGraph());
        fp1.defineOutput("out");
        fp1.connect("in", "fp2").connect("fp2", "out");

        gen.defineInput("in");
        gen.defineFlowPart("fp1", fp1.toGraph());
        gen.defineOutput("out");
        gen.connect("in", "fp1").connect("fp1", "out");

        StageGraph stages = getPlanner().plan(gen.toGraph());

        assertThat(stages.getInput().getBlockOutputs().size(), is(1));
        assertThat(stages.getOutput().getBlockInputs().size(), is(1));
        assertThat(stages.getStages().size(), is(1));

        StageBlock mr = stages.getStages().get(0);
        assertThat(mr.getMapBlocks().size(), is(1));
        assertThat(mr.getReduceBlocks().isEmpty(), is(true));

        FlowBlock mapper = single(mr.getMapBlocks());

        assertThat(FlowBlock.isConnected(
                stages.getInput().getBlockOutputs().get(0),
                mapper.getBlockInputs().get(0)), is(true));
        assertThat(FlowBlock.isConnected(
                mapper.getBlockOutputs().get(0),
                stages.getOutput().getBlockInputs().get(0)), is(true));

        assertThat(mapper.getElements().size(), is(1));
        FlowElement mapperOp = single(mapper.getElements());
        assertThat(mapperOp.getDescription(), is(fp4.desc("op1")));
    }

    /**
     * {@link StagePlanner#plan(FlowGraph)}
     */
    @Test
    public void plan_flowpart_wide() {
        FlowGraphGenerator fp2a = new FlowGraphGenerator();
        fp2a.defineInput("in");
        fp2a.defineOperator("op1", "in", "out");
        fp2a.defineOutput("out");
        fp2a.connect("in", "op1").connect("op1", "out");

        FlowGraphGenerator fp2b = new FlowGraphGenerator();
        fp2b.defineInput("in");
        fp2b.defineOperator("op2", "in", "out");
        fp2b.defineOutput("out");
        fp2b.connect("in", "op2").connect("op2", "out");

        FlowGraphGenerator fp1 = new FlowGraphGenerator();
        fp1.defineInput("in");
        fp1.defineFlowPart("fp2a", fp2a.toGraph());
        fp1.defineFlowPart("fp2b", fp2b.toGraph());
        fp1.defineOutput("out");
        fp1.connect("in", "fp2a").connect("fp2a", "fp2b").connect("fp2b", "out");

        gen.defineInput("in");
        gen.defineFlowPart("fp1", fp1.toGraph());
        gen.defineOutput("out");
        gen.connect("in", "fp1").connect("fp1", "out");

        FlowCompilerOptions options = new FlowCompilerOptions();
        options.setCompressFlowPart(true);
        StagePlanner planner = new StagePlanner(
                Collections.<FlowGraphRewriter>emptyList(),
                options);
        StageGraph stages = planner.plan(gen.toGraph());

        assertThat(stages.getInput().getBlockOutputs().size(), is(1));
        assertThat(stages.getOutput().getBlockInputs().size(), is(1));
        assertThat(stages.getStages().size(), is(1));

        StageBlock mr = stages.getStages().get(0);
        assertThat(mr.getMapBlocks().size(), is(1));
        assertThat(mr.getReduceBlocks().isEmpty(), is(true));

        FlowBlock mapper = single(mr.getMapBlocks());

        assertThat(FlowBlock.isConnected(
                stages.getInput().getBlockOutputs().get(0),
                mapper.getBlockInputs().get(0)), is(true));
        assertThat(FlowBlock.isConnected(
                mapper.getBlockOutputs().get(0),
                stages.getOutput().getBlockInputs().get(0)), is(true));

        assertThat(mapper.getElements().size(), is(2));

        FlowElement op1 = single(mapper.getBlockInputs()).getElementPort().getOwner();
        assertThat(op1.getDescription(), is(fp2a.get("op1").getDescription()));
        assertThat(succ(op1).getDescription(), is(fp2b.get("op2").getDescription()));
    }

    private void deletePseuds(FlowGraph graph) {
        for (FlowElement element : FlowGraphUtil.collectElements(graph)) {
            if (element.getDescription().getKind() == FlowElementKind.PSEUD) {
                FlowGraphUtil.skip(element);
            }
        }
    }

    private FlowElement pred(FlowElement elem) {
        return single(FlowGraphUtil.getPredecessors(elem));
    }

    private FlowElement succ(FlowElement elem) {
        return single(FlowGraphUtil.getSuccessors(elem));
    }

    private <T> T single(Iterable<T> collection) {
        Iterator<T> iter = collection.iterator();
        assert iter.hasNext() : collection;
        T result = iter.next();
        assert iter.hasNext() == false : collection;
        return result;
    }
}
TOP

Related Classes of com.asakusafw.compiler.flow.plan.StagePlannerTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.