/**
* Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.engine.view.compilation;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertFalse;
import static org.testng.AssertJUnit.assertNotNull;
import static org.testng.AssertJUnit.assertTrue;
import static org.testng.AssertJUnit.fail;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CancellationException;
import java.util.concurrent.Future;
import net.sf.ehcache.CacheManager;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import org.threeten.bp.Instant;
import com.opengamma.core.position.impl.MockPositionSource;
import com.opengamma.core.position.impl.SimplePortfolio;
import com.opengamma.core.position.impl.SimplePortfolioNode;
import com.opengamma.core.position.impl.SimplePosition;
import com.opengamma.core.security.SecuritySource;
import com.opengamma.core.security.impl.SimpleSecurity;
import com.opengamma.engine.ComputationTarget;
import com.opengamma.engine.ComputationTargetSpecification;
import com.opengamma.engine.DefaultCachingComputationTargetResolver;
import com.opengamma.engine.DefaultComputationTargetResolver;
import com.opengamma.engine.InMemorySecuritySource;
import com.opengamma.engine.depgraph.DependencyGraph;
import com.opengamma.engine.depgraph.DependencyGraphBuilderFactory;
import com.opengamma.engine.function.CachingFunctionRepositoryCompiler;
import com.opengamma.engine.function.CompiledFunctionService;
import com.opengamma.engine.function.FunctionCompilationContext;
import com.opengamma.engine.function.FunctionRepository;
import com.opengamma.engine.function.InMemoryFunctionRepository;
import com.opengamma.engine.function.resolver.DefaultFunctionResolver;
import com.opengamma.engine.marketdata.availability.FixedMarketDataAvailabilityProvider;
import com.opengamma.engine.target.ComputationTargetType;
import com.opengamma.engine.test.MockFunction;
import com.opengamma.engine.view.ResultOutputMode;
import com.opengamma.engine.view.ViewCalculationConfiguration;
import com.opengamma.engine.view.ViewDefinition;
import com.opengamma.id.ExternalId;
import com.opengamma.id.UniqueId;
import com.opengamma.id.VersionCorrection;
import com.opengamma.util.PoolExecutor;
import com.opengamma.util.ehcache.EHCacheUtils;
import com.opengamma.util.test.TestGroup;
@Test(groups = {TestGroup.UNIT, "ehcache" })
public class ViewDefinitionCompilerTest {
private CacheManager _cacheManager;
@BeforeClass
public void setUpClass() {
_cacheManager = EHCacheUtils.createTestCacheManager(getClass());
}
@AfterClass
public void tearDownClass() {
EHCacheUtils.shutdownQuiet(_cacheManager);
}
@BeforeMethod
public void setUp() {
EHCacheUtils.clear(_cacheManager);
}
//-------------------------------------------------------------------------
@Test(expectedExceptions = IllegalArgumentException.class)
public void testNullDependencyGraphs() {
new CompiledViewDefinitionWithGraphsImpl(null, null, null, null, null, null, 0);
}
public void testEmptyView() {
final ExternalId secIdentifier = ExternalId.of("SEC", "1");
final SimplePosition pos = new SimplePosition(new BigDecimal(1), secIdentifier);
final SimplePortfolioNode pn = new SimplePortfolioNode("node");
pn.addPosition(pos);
final SimplePortfolio p = new SimplePortfolio(UniqueId.of("FOO", "BAR"), "portfolio");
p.setRootNode(pn);
final MockPositionSource positionSource = new MockPositionSource();
positionSource.addPortfolio(p);
final SimpleSecurity defSec = new SimpleSecurity("");
defSec.addExternalId(secIdentifier);
final InMemorySecuritySource securitySource = new InMemorySecuritySource();
securitySource.addSecurity(defSec);
final InMemoryFunctionRepository functionRepo = new InMemoryFunctionRepository();
final FunctionCompilationContext functionCompilationContext = new FunctionCompilationContext();
functionCompilationContext.setFunctionInitId(123);
functionCompilationContext.setRawComputationTargetResolver(new DefaultCachingComputationTargetResolver(new DefaultComputationTargetResolver(securitySource, positionSource),
_cacheManager));
final CompiledFunctionService cfs = new CompiledFunctionService(functionRepo, new CachingFunctionRepositoryCompiler(), functionCompilationContext);
cfs.initialize();
final DefaultFunctionResolver functionResolver = new DefaultFunctionResolver(cfs);
final ViewCompilationServices vcs = new ViewCompilationServices(new FixedMarketDataAvailabilityProvider(), functionResolver, functionCompilationContext, new PoolExecutor(1, getClass()
.getSimpleName()),
new DependencyGraphBuilderFactory());
final ViewDefinition viewDefinition = new ViewDefinition("My View", UniqueId.of("FOO", "BAR"), "kirk");
final CompiledViewDefinitionWithGraphsImpl compiledViewDefinition = ViewDefinitionCompiler.compile(viewDefinition, vcs, Instant.now(), VersionCorrection.LATEST);
assertTrue(compiledViewDefinition.getMarketDataRequirements().isEmpty());
assertTrue(compiledViewDefinition.getDependencyGraphExplorers().isEmpty());
assertEquals(0, compiledViewDefinition.getComputationTargets().size());
}
public void testSingleValueNoLiveData() {
final ExternalId secIdentifier = ExternalId.of("SEC", "1");
final SimplePosition pos = new SimplePosition(new BigDecimal(1), secIdentifier);
final SimplePortfolioNode pn = new SimplePortfolioNode("node");
pn.addPosition(pos);
final SimplePortfolio p = new SimplePortfolio(UniqueId.of("FOO", "BAR"), "portfolio");
p.setRootNode(pn);
final MockPositionSource positionSource = new MockPositionSource();
positionSource.addPortfolio(p);
final SimpleSecurity defSec = new SimpleSecurity("My Sec");
defSec.addExternalId(secIdentifier);
final InMemorySecuritySource securitySource = new InMemorySecuritySource();
securitySource.addSecurity(defSec);
// This function doesn't actually require anything, so it can compute at the node level without anything else.
// Hence, the only target will be the node.
final MockFunction fn1 = MockFunction.getMockFunction(new ComputationTarget(ComputationTargetType.PORTFOLIO_NODE, pn), 14.2);
final InMemoryFunctionRepository functionRepo = new InMemoryFunctionRepository();
functionRepo.addFunction(fn1);
final FunctionCompilationContext functionCompilationContext = new FunctionCompilationContext();
functionCompilationContext.setFunctionInitId(123);
functionCompilationContext.setSecuritySource(securitySource);
final CompiledFunctionService cfs = new CompiledFunctionService(functionRepo, new CachingFunctionRepositoryCompiler(), functionCompilationContext);
cfs.initialize();
final DefaultFunctionResolver functionResolver = new DefaultFunctionResolver(cfs);
final DefaultCachingComputationTargetResolver computationTargetResolver = new DefaultCachingComputationTargetResolver(new DefaultComputationTargetResolver(securitySource, positionSource),
_cacheManager);
functionCompilationContext.setRawComputationTargetResolver(computationTargetResolver);
final ViewCompilationServices vcs = new ViewCompilationServices(new FixedMarketDataAvailabilityProvider(), functionResolver, functionCompilationContext, new PoolExecutor(1, getClass()
.getSimpleName()),
new DependencyGraphBuilderFactory());
final ViewDefinition viewDefinition = new ViewDefinition("My View", UniqueId.of("FOO", "BAR"), "kirk");
// We've not provided a function that targets the position level, so we can't ask for it.
viewDefinition.getResultModelDefinition().setPositionOutputMode(ResultOutputMode.NONE);
final ViewCalculationConfiguration calcConfig = new ViewCalculationConfiguration(viewDefinition, "Fibble");
calcConfig.addPortfolioRequirementName("My Sec", "OUTPUT");
viewDefinition.addViewCalculationConfiguration(calcConfig);
final CompiledViewDefinitionWithGraphsImpl compiledViewDefinition = ViewDefinitionCompiler.compile(viewDefinition, vcs, Instant.now(), VersionCorrection.LATEST);
assertTrue(compiledViewDefinition.getMarketDataRequirements().isEmpty());
assertEquals(1, compiledViewDefinition.getDependencyGraphExplorers().size());
assertNotNull(compiledViewDefinition.getDependencyGraphExplorer("Fibble"));
assertTargets(compiledViewDefinition, pn.getUniqueId());
}
public void testSingleValueExternalDependency() {
final ExternalId secIdentifier1 = ExternalId.of("SEC", "1");
final ExternalId secIdentifier2 = ExternalId.of("SEC", "2");
final SimplePosition pos = new SimplePosition(new BigDecimal(1), secIdentifier1);
final SimplePortfolioNode pn = new SimplePortfolioNode("node");
pn.addPosition(pos);
final SimplePortfolio p = new SimplePortfolio(UniqueId.of("FOO", "BAR"), "portfolio");
p.setRootNode(pn);
final MockPositionSource positionSource = new MockPositionSource();
positionSource.addPortfolio(p);
final SimpleSecurity sec1 = new SimpleSecurity("My Sec");
sec1.addExternalId(secIdentifier1);
final SimpleSecurity sec2 = new SimpleSecurity("Your Sec");
sec2.addExternalId(secIdentifier2);
final InMemorySecuritySource securitySource = new InMemorySecuritySource();
securitySource.addSecurity(sec1);
securitySource.addSecurity(sec2);
final MockFunction fn2 = MockFunction.getMockFunction("fn2", new ComputationTarget(ComputationTargetType.SECURITY, sec2), 14.2);
final MockFunction fn1 = MockFunction.getMockFunction("fn1", new ComputationTarget(ComputationTargetType.PORTFOLIO_NODE, pn), 14.2, fn2);
final InMemoryFunctionRepository functionRepo = new InMemoryFunctionRepository();
functionRepo.addFunction(fn1);
functionRepo.addFunction(fn2);
final FunctionCompilationContext functionCompilationContext = new FunctionCompilationContext();
functionCompilationContext.setFunctionInitId(123);
final CompiledFunctionService cfs = new CompiledFunctionService(functionRepo, new CachingFunctionRepositoryCompiler(), functionCompilationContext);
cfs.initialize();
final DefaultFunctionResolver functionResolver = new DefaultFunctionResolver(cfs);
final DefaultCachingComputationTargetResolver computationTargetResolver = new DefaultCachingComputationTargetResolver(new DefaultComputationTargetResolver(securitySource, positionSource),
_cacheManager);
functionCompilationContext.setRawComputationTargetResolver(computationTargetResolver);
final ViewCompilationServices vcs = new ViewCompilationServices(new FixedMarketDataAvailabilityProvider(), functionResolver, functionCompilationContext, new PoolExecutor(1, getClass()
.getSimpleName()),
new DependencyGraphBuilderFactory());
final ViewDefinition viewDefinition = new ViewDefinition("My View", UniqueId.of("FOO", "BAR"), "kirk");
viewDefinition.getResultModelDefinition().setPositionOutputMode(ResultOutputMode.NONE);
final ViewCalculationConfiguration calcConfig = new ViewCalculationConfiguration(viewDefinition, "Fibble");
calcConfig.addPortfolioRequirementName("My Sec", "OUTPUT");
viewDefinition.addViewCalculationConfiguration(calcConfig);
final CompiledViewDefinitionWithGraphsImpl compiledViewDefinition = ViewDefinitionCompiler.compile(viewDefinition, vcs, Instant.now(), VersionCorrection.LATEST);
assertTrue(compiledViewDefinition.getMarketDataRequirements().isEmpty());
assertEquals(1, compiledViewDefinition.getDependencyGraphExplorers().size());
final DependencyGraph dg = compiledViewDefinition.getDependencyGraphExplorer("Fibble").getWholeGraph();
assertNotNull(dg);
assertTrue(dg.getAllRequiredMarketData().isEmpty());
assertEquals(2, dg.getDependencyNodes().size());
// Expect the node and the security, since we've turned off position-level outputs and not actually provided a
// function that can produce them
assertTargets(compiledViewDefinition, sec2.getUniqueId(), pn.getUniqueId());
}
public void testPrimitivesOnlyNoPortfolioReference() {
final ViewDefinition viewDefinition = new ViewDefinition("Test", "jonathan");
final ViewCalculationConfiguration calcConfig = new ViewCalculationConfiguration(viewDefinition, "Config1");
viewDefinition.addViewCalculationConfiguration(calcConfig);
final UniqueId t1 = UniqueId.of("TestScheme", "t1");
final InMemoryFunctionRepository functionRepo = new InMemoryFunctionRepository();
final MockFunction f1 = MockFunction.getMockFunction(new ComputationTarget(ComputationTargetType.PRIMITIVE, t1), 42);
functionRepo.addFunction(f1);
final FunctionCompilationContext compilationContext = new FunctionCompilationContext();
compilationContext.setFunctionInitId(123);
final CompiledFunctionService cfs = new CompiledFunctionService(functionRepo, new CachingFunctionRepositoryCompiler(), compilationContext);
cfs.initialize();
final DefaultFunctionResolver functionResolver = new DefaultFunctionResolver(cfs);
final DefaultCachingComputationTargetResolver computationTargetResolver = new DefaultCachingComputationTargetResolver(new DefaultComputationTargetResolver(), _cacheManager);
compilationContext.setRawComputationTargetResolver(computationTargetResolver);
final ViewCompilationServices compilationServices = new ViewCompilationServices(new FixedMarketDataAvailabilityProvider(), functionResolver, compilationContext, new PoolExecutor(1, getClass()
.getSimpleName()),
new DependencyGraphBuilderFactory());
// We'll require r1 which can be satisfied by f1
calcConfig.addSpecificRequirement(f1.getResultSpec().toRequirementSpecification());
final CompiledViewDefinitionWithGraphsImpl compiledViewDefinition = ViewDefinitionCompiler.compile(viewDefinition, compilationServices, Instant.now(), VersionCorrection.LATEST);
assertTrue(compiledViewDefinition.getMarketDataRequirements().isEmpty());
assertEquals(1, compiledViewDefinition.getDependencyGraphExplorers().size());
assertNotNull(compiledViewDefinition.getDependencyGraphExplorer("Config1"));
assertTargets(compiledViewDefinition, t1);
}
public void testPrimitivesAndSecuritiesNoPortfolioReference() {
final ViewDefinition viewDefinition = new ViewDefinition("Test", "jonathan");
final ViewCalculationConfiguration calcConfig = new ViewCalculationConfiguration(viewDefinition, "Config1");
viewDefinition.addViewCalculationConfiguration(calcConfig);
final ExternalId secIdentifier1 = ExternalId.of("SEC", "1");
final SimpleSecurity sec1 = new SimpleSecurity("My Sec");
sec1.addExternalId(secIdentifier1);
final InMemorySecuritySource securitySource = new InMemorySecuritySource();
securitySource.addSecurity(sec1);
final UniqueId t1 = UniqueId.of("TestScheme", "t1");
final InMemoryFunctionRepository functionRepo = new InMemoryFunctionRepository();
final MockFunction f1 = MockFunction.getMockFunction("f1", new ComputationTarget(ComputationTargetType.PRIMITIVE, t1), 42);
final MockFunction f2 = MockFunction.getMockFunction("f2", new ComputationTarget(ComputationTargetType.SECURITY, sec1), 60, f1);
functionRepo.addFunction(f1);
functionRepo.addFunction(f2);
final FunctionCompilationContext compilationContext = new FunctionCompilationContext();
compilationContext.setFunctionInitId(123);
final CompiledFunctionService cfs = new CompiledFunctionService(functionRepo, new CachingFunctionRepositoryCompiler(), compilationContext);
cfs.initialize();
final DefaultFunctionResolver functionResolver = new DefaultFunctionResolver(cfs);
final DefaultCachingComputationTargetResolver computationTargetResolver = new DefaultCachingComputationTargetResolver(new DefaultComputationTargetResolver(securitySource), _cacheManager);
compilationContext.setRawComputationTargetResolver(computationTargetResolver);
final ViewCompilationServices compilationServices = new ViewCompilationServices(new FixedMarketDataAvailabilityProvider(), functionResolver, compilationContext, new PoolExecutor(1, getClass()
.getSimpleName()),
new DependencyGraphBuilderFactory());
// We'll require r2 which can be satisfied by f2, which in turn requires the output of f1
// Additionally, the security should be resolved through the ComputationTargetResolver, which only has a security
// source.
calcConfig.addSpecificRequirement(f2.getResultSpec().toRequirementSpecification());
CompiledViewDefinitionWithGraphsImpl compiledViewDefinition = ViewDefinitionCompiler.compile(viewDefinition, compilationServices, Instant.now(), VersionCorrection.LATEST);
assertTrue(compiledViewDefinition.getMarketDataRequirements().isEmpty());
assertEquals(1, compiledViewDefinition.getDependencyGraphExplorers().size());
assertNotNull(compiledViewDefinition.getDependencyGraphExplorer("Config1"));
assertTargets(compiledViewDefinition, sec1.getUniqueId(), t1);
// Turning off primitive outputs should not affect the dep graph since the primitive is needed for the security
viewDefinition.getResultModelDefinition().setPrimitiveOutputMode(ResultOutputMode.NONE);
compiledViewDefinition = ViewDefinitionCompiler.compile(viewDefinition, compilationServices, Instant.now(), VersionCorrection.LATEST);
assertTargets(compiledViewDefinition, sec1.getUniqueId(), t1);
// Turning off security outputs, even if all primitive outputs are enabled, should allow the dep graph to be
// pruned completely, since the only *terminal* output is the security output.
viewDefinition.getResultModelDefinition().setPrimitiveOutputMode(ResultOutputMode.TERMINAL_OUTPUTS);
viewDefinition.getResultModelDefinition().setSecurityOutputMode(ResultOutputMode.NONE);
compiledViewDefinition = ViewDefinitionCompiler.compile(viewDefinition, compilationServices, Instant.now(), VersionCorrection.LATEST);
assertTargets(compiledViewDefinition);
}
public void testCancel() throws Exception {
final ViewDefinition viewDefinition = new ViewDefinition("Test", "jonathan");
final ViewCalculationConfiguration calcConfig = new ViewCalculationConfiguration(viewDefinition, "Config1");
viewDefinition.addViewCalculationConfiguration(calcConfig);
final FunctionRepository functionRepo = new InMemoryFunctionRepository();
final FunctionCompilationContext compilationContext = new FunctionCompilationContext();
final CompiledFunctionService cfs = new CompiledFunctionService(functionRepo, new CachingFunctionRepositoryCompiler(), compilationContext);
cfs.initialize();
final DefaultFunctionResolver functionResolver = new DefaultFunctionResolver(cfs);
final SecuritySource securitySource = new InMemorySecuritySource();
final DefaultCachingComputationTargetResolver computationTargetResolver = new DefaultCachingComputationTargetResolver(new DefaultComputationTargetResolver(securitySource),
_cacheManager);
compilationContext.setRawComputationTargetResolver(computationTargetResolver);
final Future<CompiledViewDefinitionWithGraphsImpl> future = ViewDefinitionCompiler.fullCompileTask(viewDefinition, new ViewCompilationServices(new FixedMarketDataAvailabilityProvider(),
functionResolver, compilationContext, new PoolExecutor(1, getClass().getSimpleName()), new DependencyGraphBuilderFactory()), Instant.now(), VersionCorrection.LATEST);
assertFalse(future.isDone());
assertFalse(future.isCancelled());
assertTrue(future.cancel(true));
try {
future.get();
fail();
} catch (final CancellationException e) {
// expected
}
assertTrue(future.isCancelled());
}
private void assertTargets(final CompiledViewDefinitionWithGraphsImpl compiledViewDefinition, final UniqueId... targets) {
final Set<UniqueId> expectedTargets = new HashSet<UniqueId>(Arrays.asList(targets));
final Set<ComputationTargetSpecification> actualTargets = compiledViewDefinition.getComputationTargets();
assertEquals(expectedTargets.size(), actualTargets.size());
for (final ComputationTargetSpecification actualTarget : actualTargets) {
assertTrue(expectedTargets.contains(actualTarget.getUniqueId()));
}
}
}