/**
* Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.integration.regression;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.threeten.bp.Instant;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.opengamma.core.marketdatasnapshot.impl.ManageableMarketDataSnapshot;
import com.opengamma.engine.view.ViewDefinition;
import com.opengamma.integration.server.RemoteServer;
import com.opengamma.master.config.ConfigMaster;
import com.opengamma.master.config.ConfigSearchRequest;
import com.opengamma.master.config.ConfigSearchResult;
import com.opengamma.master.marketdatasnapshot.MarketDataSnapshotMaster;
import com.opengamma.master.marketdatasnapshot.MarketDataSnapshotSearchRequest;
import com.opengamma.master.marketdatasnapshot.MarketDataSnapshotSearchResult;
import com.opengamma.util.tuple.Pair;
import com.opengamma.util.tuple.Pairs;
/**
*
*/
public class ViewRegressionTest {
private static final Logger s_logger = LoggerFactory.getLogger(ViewRegressionTest.class);
// TODO arg for this? different deltas for different values and/or object types?
private final String _dbDumpDir;
private final Instant _valuationTime;
private final String _baseWorkingDir;
private final String _baseVersion;
private final String _baseDbConfigFile;
private final String _testWorkingDir;
private final String _serverConfigFile;
private final String _testVersion;
private final String _testDbConfigFile;
private final String _logbackConfig;
private final String _baseClasspath;
private final String _testClasspath;
public ViewRegressionTest(String projectName,
String serverConfigFile,
String dbDumpDir,
String logbackConfigFile,
Instant valuationTime,
String baseWorkingDir,
String baseVersion,
String baseDbConfigFile,
String testWorkingDir,
String testVersion,
String testDbConfigFile) {
_dbDumpDir = dbDumpDir;
_baseWorkingDir = baseWorkingDir;
_baseVersion = baseVersion;
_baseDbConfigFile = baseDbConfigFile;
_testWorkingDir = testWorkingDir;
_serverConfigFile = serverConfigFile;
_testVersion = testVersion;
_testDbConfigFile = testDbConfigFile;
_logbackConfig = "-Dlogback.configurationFile=" + logbackConfigFile;
_baseClasspath = "config:lib/" + projectName + "-" + baseVersion + ".jar";
_testClasspath = "config:lib/" + projectName + "-" + testVersion + ".jar";
_valuationTime = valuationTime;
}
public RegressionTestResults run() {
// TODO store the results in memory for now, serialize to disk/cache when it's an actual problem
// TODO fail if there are any view defs or snapshots with duplicate names
Map<Pair<String, String>, CalculationResults> testResults =
runTest(_testWorkingDir, _testClasspath, _testVersion, _testDbConfigFile);
Map<Pair<String, String>, CalculationResults> baseResults =
runTest(_baseWorkingDir, _baseClasspath, _baseVersion, _baseDbConfigFile);
List<CalculationDifference> results = Lists.newArrayList();
for (Map.Entry<Pair<String, String>, CalculationResults> entry : testResults.entrySet()) {
CalculationResults testViewResult = entry.getValue();
CalculationResults baseViewResult = baseResults.get(entry.getKey());
if (baseViewResult == null) {
s_logger.warn("No base result for {}", entry.getKey());
continue;
}
results.add(CalculationDifference.between(baseViewResult, testViewResult, ViewRegressionTestTool.DELTA));
}
return new RegressionTestResults(_baseVersion, _testVersion, results);
}
private Map<Pair<String, String>, CalculationResults> runTest(String workingDir,
String classpath,
String version,
String dbPropsFile) {
// don't use the config file to be sure we don't accidentally clobber a real database
Properties dbProps = RegressionUtils.loadProperties(dbPropsFile);
if (_dbDumpDir != null) {
RegressionUtils.createEmptyDatabase(dbPropsFile, workingDir, classpath, _logbackConfig);
RegressionUtils.restoreDatabase(workingDir, classpath, dbProps, _serverConfigFile, _logbackConfig, _dbDumpDir);
}
return runViews(workingDir, classpath, version, _valuationTime, dbProps);
}
private Map<Pair<String, String>, CalculationResults> runViews(String workingDir,
String classpath,
String version,
Instant valuationTime,
Properties dbProps) {
// TODO don't hard-code the port
int port = 8080;
String serverUrl = "http://localhost:" + port;
// start the server again to run the tests
try (ServerProcess ignored = ServerProcess.start(workingDir, classpath, _serverConfigFile, dbProps, _logbackConfig);
RemoteServer server = RemoteServer.create(serverUrl)) {
Map<Pair<String, String>, CalculationResults> allResults = Maps.newHashMap();
Collection<Pair<String, String>> viewAndSnapshotNames = getViewAndSnapshotNames(server.getConfigMaster(),
server.getMarketDataSnapshotMaster());
ViewRunner viewRunner = new ViewRunner(server.getConfigMaster(),
server.getViewProcessor(),
server.getPositionSource(),
server.getSecuritySource(),
server.getMarketDataSnapshotMaster());
for (Pair<String, String> names : viewAndSnapshotNames) {
String viewName = names.getFirst();
String snapshotName = names.getSecond();
CalculationResults results = viewRunner.run(version, viewName, snapshotName, valuationTime);
allResults.put(names, results);
}
return allResults;
}
}
private static Collection<Pair<String, String>> getViewAndSnapshotNames(ConfigMaster configMaster,
MarketDataSnapshotMaster snapshotMaster) {
List<Pair<String, String>> viewAndSnapshotNames = Lists.newArrayList();
MarketDataSnapshotSearchRequest snapshotRequest = new MarketDataSnapshotSearchRequest();
// TODO this isn't great but is necessary because of PLAT-4793
snapshotRequest.setIncludeData(true);
MarketDataSnapshotSearchResult snapshotResult = snapshotMaster.search(snapshotRequest);
for (ManageableMarketDataSnapshot snapshot : snapshotResult.getSnapshots()) {
String basisViewName = snapshot.getBasisViewName();
if (basisViewName != null) {
ConfigSearchRequest<ViewDefinition> configRequest = new ConfigSearchRequest<>(ViewDefinition.class);
configRequest.setName(basisViewName);
ConfigSearchResult<ViewDefinition> configResult = configMaster.search(configRequest);
if (configResult.getValues().size() > 1) {
s_logger.warn("Multiple view definitions found with the same name '{}'", basisViewName);
continue;
}
String viewDefName = configResult.getSingleValue().getName();
viewAndSnapshotNames.add(Pairs.of(viewDefName, snapshot.getName()));
}
}
return viewAndSnapshotNames;
}
}