/* (c) 2014 LinkedIn Corp. All rights reserved.
*
* 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.
*/
package com.linkedin.cubert.plan.physical;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.node.ObjectNode;
import org.testng.Assert;
import org.testng.annotations.Test;
import com.linkedin.cubert.plan.physical.DependencyGraph;
import com.linkedin.cubert.utils.print;
public class TestDependencyGraph
{
static class GraphCreator
{
Map<String, List<String>> edges = new HashMap<String, List<String>>();
Set<String> vertices = new HashSet<String>();
void addDependency(int parent, int depends)
{
String from = Integer.toString(depends);
String to = Integer.toString(parent);
vertices.add(to);
vertices.add(from);
List<String> list = edges.get(from);
if (list == null)
{
list = new ArrayList<String>();
edges.put(from, list);
}
list.add(to);
}
DependencyGraph getGraph()
{
DependencyGraph g = new DependencyGraph();
ObjectMapper mapper = new ObjectMapper();
for (String vertex : vertices)
{
ObjectNode json = mapper.createObjectNode();
json.put("name", vertex);
List<String> parents = edges.get(vertex);
g.addNode(vertex, parents, json);
}
return g;
}
void assertPlan()
{
List<JsonNode> plan = getGraph().getSerialPlan();
Assert.assertEquals(plan.size(), vertices.size());
Set<String> activated = new HashSet<String>();
for (JsonNode node : plan)
{
String name = node.get("name").getTextValue();
List<String> parents = edges.get(name);
print.f("Testing %s. parents=%d",
name,
parents == null ? 0 : parents.size());
if (parents != null)
{
for (String parent : parents)
{
Assert.assertTrue(activated.contains(parent));
}
}
activated.add(name);
}
}
}
@Test
public void testLinearGraph()
{
GraphCreator g = new GraphCreator();
g.addDependency(1, 2);
g.addDependency(2, 3);
g.addDependency(3, 4);
g.addDependency(4, 5);
g.assertPlan();
}
@Test
public void testDiamond()
{
GraphCreator g = new GraphCreator();
g.addDependency(1, 2);
g.addDependency(1, 3);
g.addDependency(3, 4);
g.addDependency(2, 4);
g.assertPlan();
}
@Test
public void testEmbeddedDiamond()
{
GraphCreator g = new GraphCreator();
g.addDependency(1, 2);
g.addDependency(1, 5);
g.addDependency(2, 3);
g.addDependency(2, 4);
g.addDependency(3, 6);
g.addDependency(4, 6);
g.addDependency(6, 7);
g.addDependency(5, 7);
g.assertPlan();
}
@Test(expectedExceptions = IllegalStateException.class)
public void testFullCycle()
{
GraphCreator g = new GraphCreator();
g.addDependency(1, 2);
g.addDependency(2, 3);
g.addDependency(3, 1);
g.assertPlan();
}
@Test(expectedExceptions = IllegalStateException.class)
public void testEmbeddedCycle()
{
GraphCreator g = new GraphCreator();
g.addDependency(1, 2);
g.addDependency(2, 3);
g.addDependency(3, 4);
g.addDependency(4, 2);
g.assertPlan();
}
@Test
public void testForest()
{
GraphCreator g = new GraphCreator();
g.addDependency(1, 2);
g.addDependency(3, 4);
g.addDependency(5, 6);
g.addDependency(7, 8);
g.assertPlan();
}
@Test
public void testMultiInput()
{
GraphCreator g = new GraphCreator();
g.addDependency(1, 4);
g.addDependency(2, 4);
g.addDependency(4, 5);
g.addDependency(5, 6);
g.addDependency(6, 7);
g.addDependency(3, 7);
g.addDependency(7, 8);
g.assertPlan();
}
}