/** * Copyright (C) 2014 - 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 static org.testng.AssertJUnit.assertNotNull; import java.util.Collections; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.testng.annotations.Test; import com.google.common.collect.ImmutableSet; import com.opengamma.engine.ComputationTarget; import com.opengamma.engine.depgraph.impl.DependencyGraphImpl; import com.opengamma.engine.function.FunctionCompilationContext; import com.opengamma.engine.function.FunctionExecutionContext; import com.opengamma.engine.function.FunctionInputs; import com.opengamma.engine.value.ComputedValue; import com.opengamma.engine.value.ValueProperties; import com.opengamma.engine.value.ValueRequirement; import com.opengamma.engine.value.ValueSpecification; import com.opengamma.util.test.TestGroup; import com.opengamma.util.test.TestLifecycle; /** * Tests the dependency graph building with a multiple output function whose inputs vary with its output set */ @Test(groups = TestGroup.UNIT) public class DepGraphInputMergingTest extends AbstractDependencyGraphBuilderTest { private static class VariantInputFunction extends TestFunction { private final ValueSpecification _spec1; private final ValueSpecification _spec2; private final ValueRequirement _req1; private final ValueRequirement _req2; public VariantInputFunction(final DepGraphTestHelper helper, final String in, final String out) { _spec1 = new ValueSpecification(helper.getSpec1().getValueName(), helper.getSpec1().getTargetSpecification(), helper.getSpec1().getProperties().copy().with("AUX", "X", "Y") .with("TEST", out).get()); _req1 = new ValueRequirement(helper.getRequirement1().getValueName(), helper.getRequirement1().getTargetReference(), ValueProperties.with("TEST", in).get()); _spec2 = new ValueSpecification(helper.getSpec2().getValueName(), helper.getSpec2().getTargetSpecification(), helper.getSpec2().getProperties().copy().with("AUX", "X", "Y") .with("TEST", out).get()); _req2 = new ValueRequirement(helper.getRequirement2().getValueName(), helper.getRequirement2().getTargetReference(), ValueProperties.with("TEST", in).get()); } @Override public Set<ComputedValue> execute(FunctionExecutionContext executionContext, FunctionInputs inputs, ComputationTarget target, Set<ValueRequirement> desiredValues) { return null; } private static Set<ValueRequirement> createRequirements(final ValueRequirement req, final String aux) { return Collections.singleton(aux != null ? new ValueRequirement(req.getValueName(), req.getTargetReference(), req.getConstraints().copy().with("AUX", aux).get()) : req); } @Override public Set<ValueRequirement> getRequirements(FunctionCompilationContext context, ComputationTarget target, ValueRequirement desiredValue) { final String aux = desiredValue.getConstraints().getSingleValue("AUX'"); if (desiredValue.getValueName() == _spec1.getValueName()) { return createRequirements(_req1, aux); } else { return createRequirements(_req2, aux); } } @Override public Set<ValueSpecification> getResults(final FunctionCompilationContext context, final ComputationTarget target, final Map<ValueSpecification, ValueRequirement> inputs) { final Set<ValueSpecification> result = new HashSet<ValueSpecification>(); for (ValueRequirement input : inputs.values()) { if (input.getValueName() == _req1.getValueName()) { result.add(_spec1); } else { result.add(_spec2); } } return result; } @Override public Set<ValueSpecification> getResults(FunctionCompilationContext context, ComputationTarget target) { return ImmutableSet.of(_spec1, _spec2); } } public void req1() { TestLifecycle.begin(); try { final DepGraphTestHelper helper = new DepGraphTestHelper(); helper.addFunctionProducing(new ComputedValue(helper.getSpecification1Bar(), null)); helper.addFunctionProducing(new ComputedValue(helper.getSpec2Bar(), null)); final VariantInputFunction v = new VariantInputFunction(helper, "Bar", "Foo"); helper.getFunctionRepository().addFunction(v); final DependencyGraphBuilder builder = helper.createBuilder(null); builder.addTarget(helper.getRequirement1Foo()); DependencyGraph graph = builder.getDependencyGraph(); assertNotNull(graph); assertEquals(graph.getSize(), 2); // VariantFunction & NodeProducing1 assertEquals(DependencyGraphImpl.getAllOutputSpecifications(graph), ImmutableSet.of(v._spec1, helper.getSpecification1Bar())); final ValueRequirement req = new ValueRequirement(helper.getRequirement1().getValueName(), helper.getRequirement1().getTargetReference(), ValueProperties.with("TEST", "Foo") .with("AUX", "X").get()); builder.addTarget(req); graph = builder.getDependencyGraph(); assertNotNull(graph); assertEquals(graph.getSize(), 2); // VariantFunction & NodeProducing1 assertEquals(DependencyGraphImpl.getAllOutputSpecifications(graph), ImmutableSet.of(v._spec1.compose(req), helper.getSpecification1Bar())); } finally { TestLifecycle.end(); } } public void req1_twoLevel() { TestLifecycle.begin(); try { final DepGraphTestHelper helper = new DepGraphTestHelper(); helper.addFunctionProducing(new ComputedValue(helper.getSpecification1Bar(), null)); helper.addFunctionProducing(new ComputedValue(helper.getSpec2Bar(), null)); final VariantInputFunction v1 = new VariantInputFunction(helper, "Bar", "Cow"); final VariantInputFunction v2 = new VariantInputFunction(helper, "Cow", "Foo"); helper.getFunctionRepository().addFunction(v1); helper.getFunctionRepository().addFunction(v2); final DependencyGraphBuilder builder = helper.createBuilder(null); builder.addTarget(helper.getRequirement1Foo()); DependencyGraph graph = builder.getDependencyGraph(); assertNotNull(graph); assertEquals(graph.getSize(), 3); // VariantFunction1, VariantFunction2 & NodeProducing1 assertEquals(DependencyGraphImpl.getAllOutputSpecifications(graph), ImmutableSet.of(v1._spec1, v2._spec1, helper.getSpecification1Bar())); final ValueRequirement req = new ValueRequirement(helper.getRequirement1().getValueName(), helper.getRequirement1().getTargetReference(), ValueProperties.with("TEST", "Cow") .with("AUX", "X").get()); builder.addTarget(req); graph = builder.getDependencyGraph(); assertNotNull(graph); assertEquals(graph.getSize(), 3); // VariantFunction1, VariantFunction2 & NodeProducing1 assertEquals(DependencyGraphImpl.getAllOutputSpecifications(graph), ImmutableSet.of(v1._spec1.compose(req), v2._spec1, helper.getSpecification1Bar())); } finally { TestLifecycle.end(); } } public void req2() { TestLifecycle.begin(); try { final DepGraphTestHelper helper = new DepGraphTestHelper(); helper.addFunctionProducing(new ComputedValue(helper.getSpecification1Bar(), null)); helper.addFunctionProducing(new ComputedValue(helper.getSpec2Bar(), null)); final VariantInputFunction v = new VariantInputFunction(helper, "Bar", "Foo"); helper.getFunctionRepository().addFunction(v); final DependencyGraphBuilder builder = helper.createBuilder(null); builder.addTarget(helper.getRequirement2Foo()); DependencyGraph graph = builder.getDependencyGraph(); assertNotNull(graph); assertEquals(graph.getSize(), 2); // VariantFunction & NodeProducing2 assertEquals(DependencyGraphImpl.getAllOutputSpecifications(graph), ImmutableSet.of(v._spec2, helper.getSpec2Bar())); final ValueRequirement req = new ValueRequirement(helper.getRequirement2().getValueName(), helper.getRequirement2().getTargetReference(), ValueProperties.with("TEST", "Foo") .with("AUX", "X").get()); builder.addTarget(req); graph = builder.getDependencyGraph(); assertNotNull(graph); assertEquals(graph.getSize(), 2); // VariantFunction & NodeProducing2 assertEquals(DependencyGraphImpl.getAllOutputSpecifications(graph), ImmutableSet.of(v._spec2.compose(req), helper.getSpec2Bar())); } finally { TestLifecycle.end(); } } public void req2_twoLevel() { TestLifecycle.begin(); try { final DepGraphTestHelper helper = new DepGraphTestHelper(); helper.addFunctionProducing(new ComputedValue(helper.getSpecification1Bar(), null)); helper.addFunctionProducing(new ComputedValue(helper.getSpec2Bar(), null)); final VariantInputFunction v1 = new VariantInputFunction(helper, "Bar", "Cow"); final VariantInputFunction v2 = new VariantInputFunction(helper, "Cow", "Foo"); helper.getFunctionRepository().addFunction(v1); helper.getFunctionRepository().addFunction(v2); final DependencyGraphBuilder builder = helper.createBuilder(null); builder.addTarget(helper.getRequirement2Foo()); DependencyGraph graph = builder.getDependencyGraph(); assertNotNull(graph); assertEquals(graph.getSize(), 3); // VariantFunction1, VariantFunction2 & NodeProducing2 assertEquals(DependencyGraphImpl.getAllOutputSpecifications(graph), ImmutableSet.of(v1._spec2, v2._spec2, helper.getSpec2Bar())); final ValueRequirement req = new ValueRequirement(helper.getRequirement2().getValueName(), helper.getRequirement2().getTargetReference(), ValueProperties.with("TEST", "Cow") .with("AUX", "X").get()); builder.addTarget(req); graph = builder.getDependencyGraph(); assertNotNull(graph); assertEquals(graph.getSize(), 3); // VariantFunction1, VariantFunction2 & NodeProducing2 assertEquals(DependencyGraphImpl.getAllOutputSpecifications(graph), ImmutableSet.of(v1._spec2.compose(req), v2._spec2, helper.getSpec2Bar())); } finally { TestLifecycle.end(); } } public void req1And2() { TestLifecycle.begin(); try { final DepGraphTestHelper helper = new DepGraphTestHelper(); helper.addFunctionProducing(new ComputedValue(helper.getSpecification1Bar(), null)); helper.addFunctionProducing(new ComputedValue(helper.getSpec2Bar(), null)); final VariantInputFunction v = new VariantInputFunction(helper, "Bar", "Foo"); helper.getFunctionRepository().addFunction(v); final DependencyGraphBuilder builder = helper.createBuilder(null); builder.addTarget(helper.getRequirement1Foo()); builder.addTarget(helper.getRequirement2Foo()); DependencyGraph graph = builder.getDependencyGraph(); assertNotNull(graph); assertEquals(graph.getSize(), 3); // VariantFunction (with two outputs), NodeProducing1 and NodeProducing2 assertEquals(DependencyGraphImpl.getAllOutputSpecifications(graph), ImmutableSet.of(v._spec1, v._spec2, helper.getSpecification1Bar(), helper.getSpec2Bar())); final ValueRequirement req = new ValueRequirement(helper.getRequirement1().getValueName(), helper.getRequirement1().getTargetReference(), ValueProperties.with("TEST", "Foo") .with("AUX", "X").get()); builder.addTarget(req); graph = builder.getDependencyGraph(); assertNotNull(graph); assertEquals(graph.getSize(), 3); // VariantFunction (with two outputs), NodeProducing1 and NodeProducing2 assertEquals(DependencyGraphImpl.getAllOutputSpecifications(graph), ImmutableSet.of(v._spec1.compose(req), v._spec2, helper.getSpecification1Bar(), helper.getSpec2Bar())); } finally { TestLifecycle.end(); } } public void req1And2_threeLevel() { TestLifecycle.begin(); try { final DepGraphTestHelper helper = new DepGraphTestHelper(); helper.addFunctionProducing(new ComputedValue(helper.getSpecification1Bar(), null)); helper.addFunctionProducing(new ComputedValue(helper.getSpec2Bar(), null)); final VariantInputFunction v1 = new VariantInputFunction(helper, "Bar", "Cow"); final VariantInputFunction v2 = new VariantInputFunction(helper, "Cow", "Dog"); final VariantInputFunction v3 = new VariantInputFunction(helper, "Dog", "Foo"); helper.getFunctionRepository().addFunction(v1); helper.getFunctionRepository().addFunction(v2); helper.getFunctionRepository().addFunction(v3); final DependencyGraphBuilder builder = helper.createBuilder(null); builder.addTarget(helper.getRequirement1Foo()); builder.addTarget(helper.getRequirement2Foo()); DependencyGraph graph = builder.getDependencyGraph(); assertNotNull(graph); assertEquals(graph.getSize(), 5); // v1, v2, v3, NodeProducing1 and NodeProducing2 assertEquals(DependencyGraphImpl.getAllOutputSpecifications(graph), ImmutableSet.of(v1._spec1, v1._spec2, v2._spec1, v2._spec2, v3._spec1, v3._spec2, helper.getSpecification1Bar(), helper.getSpec2Bar())); final ValueRequirement req1 = new ValueRequirement(helper.getRequirement1().getValueName(), helper.getRequirement1().getTargetReference(), ValueProperties.with("TEST", "Cow") .with("AUX", "X").get()); builder.addTarget(req1); graph = builder.getDependencyGraph(); assertNotNull(graph); assertEquals(graph.getSize(), 5); // v1, v2, v3, NodeProducing1 and NodeProducing2 assertEquals(DependencyGraphImpl.getAllOutputSpecifications(graph), ImmutableSet.of(v1._spec1.compose(req1), v1._spec2, v2._spec1, v2._spec2, v3._spec1, v3._spec2, helper.getSpecification1Bar(), helper.getSpec2Bar())); final ValueRequirement req2 = new ValueRequirement(helper.getRequirement2().getValueName(), helper.getRequirement2().getTargetReference(), ValueProperties.with("TEST", "Cow") .with("AUX", "X").get()); builder.addTarget(req2); graph = builder.getDependencyGraph(); assertNotNull(graph); assertEquals(graph.getSize(), 5); // v1, v2, v3, NodeProducing1 and NodeProducing2 assertEquals(DependencyGraphImpl.getAllOutputSpecifications(graph), ImmutableSet.of(v1._spec1.compose(req1), v1._spec2.compose(req2), v2._spec1, v2._spec2, v3._spec1, v3._spec2, helper.getSpecification1Bar(), helper.getSpec2Bar())); final ValueRequirement req3 = new ValueRequirement(helper.getRequirement2().getValueName(), helper.getRequirement2().getTargetReference(), ValueProperties.with("TEST", "Dog") .with("AUX", "Y").get()); builder.addTarget(req3); graph = builder.getDependencyGraph(); assertNotNull(graph); assertEquals(graph.getSize(), 5); // v1, v2, v3, NodeProducing1 and NodeProducing2 assertEquals(DependencyGraphImpl.getAllOutputSpecifications(graph), ImmutableSet.of(v1._spec1.compose(req1), v1._spec2.compose(req2), v2._spec1, v2._spec2.compose(req3), v3._spec1, v3._spec2, helper.getSpecification1Bar(), helper.getSpec2Bar())); } finally { TestLifecycle.end(); } } public void req1And2_insitu_rewrite() { TestLifecycle.begin(); try { final DepGraphTestHelper helper = new DepGraphTestHelper(); helper.addFunctionProducing(new ComputedValue(helper.getSpecification1Bar(), null)); helper.addFunctionProducing(new ComputedValue(helper.getSpec2Bar(), null)); final VariantInputFunction v1 = new VariantInputFunction(helper, "Bar", "Cow"); final VariantInputFunction v2 = new VariantInputFunction(helper, "Cow", "Dog"); final VariantInputFunction v3 = new VariantInputFunction(helper, "Dog", "Foo"); helper.getFunctionRepository().addFunction(v1); helper.getFunctionRepository().addFunction(v2); helper.getFunctionRepository().addFunction(v3); final DependencyGraphBuilder builder = helper.createBuilder(null); builder.addTarget(helper.getRequirement1Foo()); builder.addTarget(helper.getRequirement2Foo()); DependencyGraph graph = builder.getDependencyGraph(); assertNotNull(graph); assertEquals(graph.getSize(), 5); // v1, v2, v3, NodeProducing1 and NodeProducing2 assertEquals(DependencyGraphImpl.getAllOutputSpecifications(graph), ImmutableSet.of(v1._spec1, v1._spec2, v2._spec1, v2._spec2, v3._spec1, v3._spec2, helper.getSpecification1Bar(), helper.getSpec2Bar())); // Asking for this will cause a rewrite of the v1->v2 edge during the graph build ([PLAT-6321] error) final ValueRequirement req = new ValueRequirement(helper.getRequirement2().getValueName(), helper.getRequirement2().getTargetReference(), ValueProperties.with("TEST", "Dog") .with("AUX", "Y").withOptional("AUX'").with("AUX'", "X").get()); // This is the implied requirement that will be requested and used for the edge re-write above (needed to check the graph below) final ValueRequirement ireq = new ValueRequirement(helper.getRequirement2().getValueName(), helper.getRequirement2().getTargetReference(), ValueProperties.with("AUX", "X").get()); builder.addTarget(req); graph = builder.getDependencyGraph(); assertNotNull(graph); assertEquals(graph.getSize(), 5); // v1, v2, v3, NodeProducing1 and NodeProducing2 assertEquals(DependencyGraphImpl.getAllOutputSpecifications(graph), ImmutableSet.of(v1._spec1, v1._spec2.compose(ireq), v2._spec1, v2._spec2.compose(req), v3._spec1, v3._spec2, helper.getSpecification1Bar(), helper.getSpec2Bar())); } finally { TestLifecycle.end(); } } }