/** * Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.engine.depgraph; import static org.testng.Assert.assertEquals; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.annotations.Test; import com.google.common.collect.ImmutableSet; import com.opengamma.engine.ComputationTarget; import com.opengamma.engine.ComputationTargetSpecification; import com.opengamma.engine.function.AbstractFunction; import com.opengamma.engine.function.CompiledFunctionDefinition; import com.opengamma.engine.function.FunctionCompilationContext; import com.opengamma.engine.function.FunctionInvoker; import com.opengamma.engine.target.ComputationTargetType; import com.opengamma.engine.value.ValueRequirement; import com.opengamma.engine.value.ValueSpecification; import com.opengamma.id.UniqueId; import com.opengamma.util.test.TestGroup; import com.opengamma.util.test.TestLifecycle; /** * Tests the dependency graph building when two targets can be merged to create a composite equivalent to both. */ @Test(groups = TestGroup.UNIT) public class DepGraphTargetMergingTest extends AbstractDependencyGraphBuilderTest { private static final Logger s_logger = LoggerFactory.getLogger(DepGraphTargetMergingTest.class); private static final class MergeableFunction extends AbstractFunction.NonCompiled { private final ValueRequirement _req1; private final ValueRequirement _req2; public MergeableFunction(final ValueRequirement req1, final ValueRequirement req2) { _req1 = req1; _req2 = req2; } @Override public ComputationTargetType getTargetType() { return ComputationTargetType.PRIMITIVE; } @Override public Set<ValueSpecification> getResults(final FunctionCompilationContext context, final ComputationTarget target) { return Collections.singleton(new ValueSpecification("Foo", target.toSpecification(), createValueProperties().get())); } @Override public Set<ValueRequirement> getRequirements(final FunctionCompilationContext context, final ComputationTarget target, final ValueRequirement desiredValue) { if (target.getUniqueId().getValue().startsWith("0")) { return Collections.emptySet(); } else if (target.getUniqueId().getValue().startsWith("1")) { return Collections.singleton(_req1); } else if (target.getUniqueId().getValue().startsWith("2")) { return Collections.singleton(_req2); } else if (target.getUniqueId().getValue().startsWith("3")) { return ImmutableSet.of(_req1, _req2); } else if (target.getUniqueId().getValue().startsWith("4")) { return ImmutableSet.of(new ValueRequirement("Foo", ComputationTargetSpecification.of(UniqueId.of("Test", "2A"))), new ValueRequirement("Foo", ComputationTargetSpecification.of(UniqueId.of("Test", "2B"))), new ValueRequirement("Foo", ComputationTargetSpecification.of(UniqueId.of("Test", "3A"))), new ValueRequirement("Foo", ComputationTargetSpecification.of(UniqueId.of("Test", "3B"))), new ValueRequirement("Foo", ComputationTargetSpecification.of(UniqueId.of("Test", "0C"))), _req1, _req2); } else { throw new IllegalStateException(); } } @Override public FunctionInvoker getFunctionInvoker() { return null; } } private static final class ConsumerFunction extends AbstractFunction.NonCompiled { @Override public ComputationTargetType getTargetType() { return ComputationTargetType.PRIMITIVE; } @Override public Set<ValueSpecification> getResults(final FunctionCompilationContext context, final ComputationTarget target) { return Collections.singleton(new ValueSpecification("Bar", target.toSpecification(), createValueProperties().get())); } @Override public Set<ValueRequirement> getRequirements(final FunctionCompilationContext context, final ComputationTarget target, final ValueRequirement desiredValue) { return Collections.singleton(new ValueRequirement("Foo", target.toSpecification())); } @Override public FunctionInvoker getFunctionInvoker() { return null; } } @Override protected DepGraphTestHelper helper() { final DepGraphTestHelper helper = super.helper(); helper.addFunctionProducing2(); helper.addFunctionRequiring2Producing1(); helper.getFunctionRepository().addFunction(new MergeableFunction(helper.getRequirement1(), helper.getRequirement2())); helper.getFunctionRepository().addFunction(new ConsumerFunction()); return helper; } protected ComputationTargetCollapser collapser() { final DefaultComputationTargetCollapser collapser = new DefaultComputationTargetCollapser(); collapser.addCollapser(ComputationTargetType.PRIMITIVE, new ComputationTargetCollapser() { private void add(final Collection<String> ids, final ComputationTargetSpecification target) { final String v = target.getUniqueId().getValue(); for (int i = 0; i < v.length(); i += 2) { ids.add(v.substring(i, i + 2)); } } @Override public boolean canApplyTo(final ComputationTargetSpecification a) { return "Test".equals(a.getUniqueId().getScheme()); } @Override public ComputationTargetSpecification collapse(final CompiledFunctionDefinition function, final ComputationTargetSpecification a, final ComputationTargetSpecification b) { s_logger.debug("Collapse {} on {} + {}", new Object[] {function, a, b }); if ((function instanceof MergeableFunction) && (a.getUniqueId().getValue().charAt(0) == b.getUniqueId().getValue().charAt(0))) { final Set<String> idSet = new HashSet<String>(); add(idSet, a); add(idSet, b); final List<String> idList = new ArrayList<String>(idSet); Collections.sort(idList); final StringBuilder sb = new StringBuilder(); for (final String id : idList) { sb.append(id); } return a.replaceIdentifier(UniqueId.of("Test", sb.toString())); } else { return null; } } }); return collapser; } private Set<String> getTargets(final DependencyGraph graph) { final Set<String> identifiers = new HashSet<String>(); final Iterator<DependencyNode> itr = graph.nodeIterator(); while (itr.hasNext()) { final DependencyNode node = itr.next(); identifiers.add(node.getTarget().getUniqueId().getValue()); } return identifiers; } public void testNoInputsNoOutputs() { TestLifecycle.begin(); try { final DependencyGraphBuilder builder = helper().createBuilder(null); builder.setComputationTargetCollapser(collapser()); builder.addTarget(new ValueRequirement("Foo", ComputationTargetSpecification.of(UniqueId.of("Test", "0A")))); builder.addTarget(new ValueRequirement("Foo", ComputationTargetSpecification.of(UniqueId.of("Test", "0B")))); builder.addTarget(new ValueRequirement("Foo", ComputationTargetSpecification.of(UniqueId.of("Test", "0C")))); final DependencyGraph graph = builder.getDependencyGraph(); assertEquals(graph.getSize(), 1); // Foo(0A0B0C) assertEquals(getTargets(graph), ImmutableSet.of("0A0B0C")); } finally { TestLifecycle.end(); } } public void testNoInputs() { TestLifecycle.begin(); try { final DepGraphTestHelper helper = helper(); final DependencyGraphBuilder builder = helper.createBuilder(null); builder.setComputationTargetCollapser(collapser()); builder.addTarget(new ValueRequirement("Bar", ComputationTargetSpecification.of(UniqueId.of("Test", "0A")))); builder.addTarget(new ValueRequirement("Bar", ComputationTargetSpecification.of(UniqueId.of("Test", "0B")))); builder.addTarget(new ValueRequirement("Bar", ComputationTargetSpecification.of(UniqueId.of("Test", "0C")))); final DependencyGraph graph = builder.getDependencyGraph(); assertEquals(graph.getSize(), 4); // Foo(0A0B0C) -> { Bar(0A), Bar(0B), Bar(0C) } assertEquals(getTargets(graph), ImmutableSet.of("0A0B0C", "0A", "0B", "0C")); } finally { TestLifecycle.end(); } } public void testNoOutputs() { TestLifecycle.begin(); try { final DepGraphTestHelper helper = helper(); final DependencyGraphBuilder builder = helper.createBuilder(null); builder.setComputationTargetCollapser(collapser()); builder.addTarget(new ValueRequirement("Foo", ComputationTargetSpecification.of(UniqueId.of("Test", "0A")))); builder.addTarget(new ValueRequirement("Foo", ComputationTargetSpecification.of(UniqueId.of("Test", "0B")))); builder.addTarget(new ValueRequirement("Foo", ComputationTargetSpecification.of(UniqueId.of("Test", "0C")))); builder.addTarget(new ValueRequirement("Foo", ComputationTargetSpecification.of(UniqueId.of("Test", "1A")))); builder.addTarget(new ValueRequirement("Foo", ComputationTargetSpecification.of(UniqueId.of("Test", "1B")))); builder.addTarget(new ValueRequirement("Foo", ComputationTargetSpecification.of(UniqueId.of("Test", "1C")))); builder.addTarget(new ValueRequirement("Foo", ComputationTargetSpecification.of(UniqueId.of("Test", "2A")))); builder.addTarget(new ValueRequirement("Foo", ComputationTargetSpecification.of(UniqueId.of("Test", "2B")))); builder.addTarget(new ValueRequirement("Foo", ComputationTargetSpecification.of(UniqueId.of("Test", "2C")))); builder.addTarget(new ValueRequirement("Foo", ComputationTargetSpecification.of(UniqueId.of("Test", "3A")))); builder.addTarget(new ValueRequirement("Foo", ComputationTargetSpecification.of(UniqueId.of("Test", "3B")))); builder.addTarget(new ValueRequirement("Foo", ComputationTargetSpecification.of(UniqueId.of("Test", "3C")))); final DependencyGraph graph = builder.getDependencyGraph(); assertEquals(graph.getSize(), 6); // Foo(0A0B0C), Req1 -> Foo(1A1B1C), Req2 -> Foo(2A2B2C), { Req1, Req2 } -> Foo(3A3B3C) assertEquals(getTargets(graph), ImmutableSet.of("0A0B0C", "1A1B1C", "2A2B2C", "3A3B3C", helper.getTarget().toSpecification().getUniqueId().getValue())); } finally { TestLifecycle.end(); } } public void testFull() { TestLifecycle.begin(); try { final DepGraphTestHelper helper = helper(); final DependencyGraphBuilder builder = helper.createBuilder(null); builder.setComputationTargetCollapser(collapser()); builder.addTarget(new ValueRequirement("Foo", ComputationTargetSpecification.of(UniqueId.of("Test", "0A")))); builder.addTarget(new ValueRequirement("Bar", ComputationTargetSpecification.of(UniqueId.of("Test", "0B")))); builder.addTarget(new ValueRequirement("Foo", ComputationTargetSpecification.of(UniqueId.of("Test", "0C")))); builder.addTarget(new ValueRequirement("Bar", ComputationTargetSpecification.of(UniqueId.of("Test", "1A")))); builder.addTarget(new ValueRequirement("Foo", ComputationTargetSpecification.of(UniqueId.of("Test", "1B")))); builder.addTarget(new ValueRequirement("Bar", ComputationTargetSpecification.of(UniqueId.of("Test", "1C")))); builder.addTarget(new ValueRequirement("Foo", ComputationTargetSpecification.of(UniqueId.of("Test", "2A")))); builder.addTarget(new ValueRequirement("Bar", ComputationTargetSpecification.of(UniqueId.of("Test", "2B")))); builder.addTarget(new ValueRequirement("Foo", ComputationTargetSpecification.of(UniqueId.of("Test", "2C")))); builder.addTarget(new ValueRequirement("Bar", ComputationTargetSpecification.of(UniqueId.of("Test", "3A")))); builder.addTarget(new ValueRequirement("Foo", ComputationTargetSpecification.of(UniqueId.of("Test", "3B")))); builder.addTarget(new ValueRequirement("Bar", ComputationTargetSpecification.of(UniqueId.of("Test", "3C")))); final DependencyGraph graph = builder.getDependencyGraph(); assertEquals(graph.getSize(), 12); // Foo(0A0B0C) -> Bar(0B), Req1 -> Foo(1A1B1C) -> { Bar(1A), Bar(1C) }, Req2 -> Foo(2A2B2C) -> Bar(2B), { Req1, Req2 } -> Foo(3A3B3C) -> { Bar(3A), Bar (3C) } assertEquals(getTargets(graph), ImmutableSet.of("0A0B0C", "1A1B1C", "2A2B2C", "3A3B3C", helper.getTarget().toSpecification().getUniqueId().getValue(), "0B", "1A", "1C", "2B", "3A", "3C")); } finally { TestLifecycle.end(); } } public void testTwoLevelCollapse() { TestLifecycle.begin(); try { final DepGraphTestHelper helper = helper(); final DependencyGraphBuilder builder = helper.createBuilder(null); builder.setComputationTargetCollapser(collapser()); builder.addTarget(new ValueRequirement("Foo", ComputationTargetSpecification.of(UniqueId.of("Test", "4A")))); builder.addTarget(new ValueRequirement("Foo", ComputationTargetSpecification.of(UniqueId.of("Test", "4B")))); builder.addTarget(new ValueRequirement("Foo", ComputationTargetSpecification.of(UniqueId.of("Test", "4C")))); builder.addTarget(new ValueRequirement("Foo", ComputationTargetSpecification.of(UniqueId.of("Test", "4D")))); builder.addTarget(new ValueRequirement("Foo", ComputationTargetSpecification.of(UniqueId.of("Test", "4E")))); builder.addTarget(new ValueRequirement("Foo", ComputationTargetSpecification.of(UniqueId.of("Test", "4F")))); final DependencyGraph graph = builder.getDependencyGraph(); assertEquals(graph.getSize(), 6); assertEquals(getTargets(graph), ImmutableSet.of("0C", "2A2B", "3A3B", "4A4B4C4D4E4F", helper.getTarget().toSpecification().getUniqueId().getValue())); } finally { TestLifecycle.end(); } } }