/** * 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.io.BufferedWriter; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.Writer; import java.util.Collections; import java.util.List; import java.util.Map; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.Option; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import org.apache.commons.cli.PosixParser; import org.fudgemsg.FudgeMsg; import org.fudgemsg.MutableFudgeMsg; import org.fudgemsg.mapping.FudgeDeserializer; import org.fudgemsg.mapping.FudgeSerializer; import org.fudgemsg.wire.FudgeMsgReader; import org.fudgemsg.wire.FudgeMsgWriter; import org.fudgemsg.wire.xml.FudgeXMLStreamReader; import org.fudgemsg.wire.xml.FudgeXMLStreamWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.threeten.bp.Instant; import com.google.common.collect.Lists; import com.opengamma.scripts.Scriptable; import com.opengamma.util.fudgemsg.OpenGammaFudgeContext; import com.opengamma.util.tuple.Pair; /** * */ @Scriptable public class ViewRegressionTestTool { public static final double DELTA = 0.0001; private static final Options OPTIONS = createOptions(); private static final String PROJECT_NAME = "pn"; private static final String SERVER_CONFIG = "sc"; private static final String DB_DUMP_DIR = "dd"; private static final String LOGBACK_CONFIG = "l"; private static final String VALUATION_TIME = "vt"; private static final String BASE_DIR = "bd"; private static final String TEST_DIR = "td"; private static final String BASE_VERSION = "bv"; private static final String TEST_VERSION = "tv"; private static final String BASE_PROPS = "bp"; private static final String TEST_PROPS = "tp"; private static final String HELP = "h"; private static final String REPORT_FILE = "rf"; private static final String DEFAULT_REPORT_FILE = "regression-report.txt"; private static final String RESULT_OUT = "resultout"; private static final String RESULT_IN = "resultin"; private static final Logger s_logger = LoggerFactory.getLogger(ViewRegressionTestTool.class); /** * Main method to run the tool. * * @param args the arguments, unused */ public static void main(String[] args) throws Exception { // CSIGNORE try { TestStatus status = ViewRegressionTestTool.run(args); System.exit(status.ordinal()); } catch (Exception e) { e.printStackTrace(); System.exit(TestStatus.ERROR.ordinal()); } } private static void printUsage() { HelpFormatter formatter = new HelpFormatter(); formatter.setWidth(120); formatter.printHelp("java " + ViewRegressionTestTool.class.getName(), OPTIONS, true); } private static TestStatus run(String[] args) throws Exception { CommandLineParser parser = new PosixParser(); CommandLine cl; try { cl = parser.parse(OPTIONS, args); } catch (final ParseException e) { printUsage(); return TestStatus.ERROR; } if (cl.hasOption(HELP)) { printUsage(); return TestStatus.ERROR; } if (cl.hasOption(RESULT_OUT) && (!cl.hasOption(BASE_DIR) || !cl.hasOption(BASE_VERSION) || !cl.hasOption(BASE_PROPS))) { printUsage(); return TestStatus.ERROR; } if (cl.hasOption(RESULT_IN) && (!cl.hasOption(TEST_DIR) || !cl.hasOption(TEST_VERSION) || !cl.hasOption(TEST_PROPS))) { printUsage(); return TestStatus.ERROR; } if (!cl.hasOption(RESULT_IN) && !cl.hasOption(RESULT_OUT) && (!cl.hasOption(BASE_DIR) || !cl.hasOption(BASE_VERSION) || !cl.hasOption(BASE_PROPS) || !cl.hasOption(TEST_DIR) || !cl.hasOption(TEST_VERSION) || !cl.hasOption(TEST_PROPS))) { printUsage(); return TestStatus.ERROR; } Instant valuationTime; if (cl.hasOption(VALUATION_TIME)) { valuationTime = Instant.parse(cl.getOptionValue(VALUATION_TIME)); } else { // NOTE jonathan 2013-12-10 -- imply the valuation time from the market data source. // We should never be using Instant.now() as the valuation time in regression tests - the results would be meaningless. valuationTime = null; } if (cl.hasOption(RESULT_OUT) || cl.hasOption(RESULT_IN)) { final CreateGoldenCopyForRegressionTest test; if (cl.hasOption(RESULT_OUT)) { test = new CreateGoldenCopyForRegressionTest(cl.getOptionValue(PROJECT_NAME), cl.getOptionValue(SERVER_CONFIG), cl.getOptionValue(DB_DUMP_DIR), cl.getOptionValue(LOGBACK_CONFIG), valuationTime, cl.getOptionValue(BASE_DIR), cl.getOptionValue(BASE_VERSION), cl.getOptionValue(BASE_PROPS)); } else { test = new CreateGoldenCopyForRegressionTest(cl.getOptionValue(PROJECT_NAME), cl.getOptionValue(SERVER_CONFIG), cl.getOptionValue(DB_DUMP_DIR), cl.getOptionValue(LOGBACK_CONFIG), valuationTime, cl.getOptionValue(TEST_DIR), cl.getOptionValue(TEST_VERSION), cl.getOptionValue(TEST_PROPS)); } Map<Pair<String, String>, CalculationResults> results = test.run(); if (cl.hasOption(RESULT_OUT)) { String resultFileName = cl.getOptionValue(RESULT_OUT); FudgeSerializer serializer = new FudgeSerializer(OpenGammaFudgeContext.getInstance()); try (FileWriter writer = new FileWriter(new File(resultFileName))) { FudgeXMLStreamWriter streamWriter = new FudgeXMLStreamWriter(OpenGammaFudgeContext.getInstance(), writer); FudgeMsgWriter fudgeMsgWriter = new FudgeMsgWriter(streamWriter); MutableFudgeMsg msg = serializer.objectToFudgeMsg(results); fudgeMsgWriter.writeMessage(msg); writer.append("\n"); fudgeMsgWriter.flush(); } } if (cl.hasOption(RESULT_IN)) { String inputFileName = cl.getOptionValue(RESULT_IN); FudgeDeserializer deserializer = new FudgeDeserializer(OpenGammaFudgeContext.getInstance()); try (FileReader reader = new FileReader(new File(inputFileName))) { FudgeXMLStreamReader streamReader = new FudgeXMLStreamReader(OpenGammaFudgeContext.getInstance(), reader); FudgeMsgReader fudgeMsgReader = new FudgeMsgReader(streamReader); final RegressionTestResults regressionTestResults; if (fudgeMsgReader.hasNext()) { FudgeMsg fudgeMsg = fudgeMsgReader.nextMessage(); Map<Pair<String, String>, CalculationResults> exemplarResults = (Map<Pair<String, String>, CalculationResults>) deserializer.fudgeMsgToObject( fudgeMsg); List<CalculationDifference> calculationDifferences = Lists.newArrayList(); for (Map.Entry<Pair<String, String>, CalculationResults> entry : results.entrySet()) { CalculationResults testViewResult = entry.getValue(); CalculationResults exemplarResult = exemplarResults.get(entry.getKey()); if (exemplarResult == null) { s_logger.warn("No exemplar result for {}", entry.getKey()); continue; } calculationDifferences.add(CalculationDifference.between(exemplarResult, testViewResult, DELTA)); } regressionTestResults = new RegressionTestResults(cl.getOptionValue(TEST_VERSION), cl.getOptionValue(TEST_VERSION), calculationDifferences); } else { regressionTestResults = new RegressionTestResults(cl.getOptionValue(TEST_VERSION), cl.getOptionValue(TEST_VERSION), Collections.<CalculationDifference>emptyList()); } try (Writer writer = new BufferedWriter(new FileWriter(cl.getOptionValue(REPORT_FILE, DEFAULT_REPORT_FILE)))) { ReportGenerator.generateReport(regressionTestResults, ReportGenerator.Format.TEXT, writer); } return regressionTestResults.getStatus(); } } else { return TestStatus.PASS; } } else { ViewRegressionTest test = new ViewRegressionTest(cl.getOptionValue(PROJECT_NAME), cl.getOptionValue(SERVER_CONFIG), cl.getOptionValue(DB_DUMP_DIR), cl.getOptionValue(LOGBACK_CONFIG), valuationTime, cl.getOptionValue(BASE_DIR), cl.getOptionValue(BASE_VERSION), cl.getOptionValue(BASE_PROPS), cl.getOptionValue(TEST_DIR), cl.getOptionValue(TEST_VERSION), cl.getOptionValue(TEST_PROPS)); RegressionTestResults results = test.run(); try (Writer writer = new BufferedWriter(new FileWriter(cl.getOptionValue(REPORT_FILE, DEFAULT_REPORT_FILE)))) { ReportGenerator.generateReport(results, ReportGenerator.Format.TEXT, writer); } /*FudgeSerializer serializer = new FudgeSerializer(OpenGammaFudgeContext.getInstance()); try (FileWriter writer = new FileWriter(new File("/Users/chris/tmp/regression/results.xml"))) { FudgeXMLStreamWriter streamWriter = new FudgeXMLStreamWriter(OpenGammaFudgeContext.getInstance(), writer); FudgeMsgWriter fudgeMsgWriter = new FudgeMsgWriter(streamWriter); MutableFudgeMsg msg = serializer.objectToFudgeMsg(results); FudgeSerializer.addClassHeader(msg, results.getClass()); fudgeMsgWriter.writeMessage(msg); writer.append("\n"); fudgeMsgWriter.flush(); }*/ return results.getStatus(); } } private static Options createOptions() { Options options = new Options(); // TODO extra options - java executable, arbitrary additional jvm args (for memory, GC config etc) Option resultout = new Option(RESULT_OUT, "resultout", true, "Flag indicationg whether and into what file, store the results of running singe server tests as opposed to run regression test comparing two servers."); resultout.setRequired(false); options.addOption(resultout); Option resultin = new Option(RESULT_IN, "resultin", true, "Flag indicationg whether and into what file, store the results of running singe server tests as opposed to run regression test comparing two servers."); resultin.setRequired(false); options.addOption(resultin); Option projectNameOption = new Option(PROJECT_NAME, "projectname", true, "Project name (as used in the build artifacts)"); projectNameOption.setRequired(true); options.addOption(projectNameOption); Option serverConfigOption = new Option(SERVER_CONFIG, "serverconfig", true, "Configuration file used to run the server"); serverConfigOption.setRequired(true); options.addOption(serverConfigOption); Option dbDumpDirOption = new Option(DB_DUMP_DIR, "dbdumpdir", true, "Directory containing the database dump files." + " If this is omitted the database won't be created or populated, the existing database will be used"); options.addOption(dbDumpDirOption); Option logbackConfigOption = new Option(LOGBACK_CONFIG, "logbackconfig", true, "Logback config for the servers"); options.addOption(logbackConfigOption); Option valuationTimeOption = new Option(VALUATION_TIME, "valuationtime", true, "Valuation time for the views"); options.addOption(valuationTimeOption); Option baseDirOption = new Option(BASE_DIR, "basedir", true, "Installation directory for the base version of the server"); //baseDirOption.setRequired(true); options.addOption(baseDirOption); Option newDirOption = new Option(TEST_DIR, "testdir", true, "Installation directory for the test version of the server"); //newDirOption.setRequired(true); options.addOption(newDirOption); Option baseVersionOption = new Option(BASE_VERSION, "baseversion", true, "Version of the base server"); //baseVersionOption.setRequired(true); options.addOption(baseVersionOption); Option newVersionOption = new Option(TEST_VERSION, "testversion", true, "Version of the test server"); //newVersionOption.setRequired(true); options.addOption(newVersionOption); Option basePropsOption = new Option(BASE_PROPS, "baseprops", true, "The DB properties file for the base server"); //basePropsOption.setRequired(true); options.addOption(basePropsOption); Option newPropsOption = new Option(TEST_PROPS, "testprops", true, "The DB properties file for the test server"); //newPropsOption.setRequired(true); options.addOption(newPropsOption); Option helpOption = new Option(HELP, "help", true, "Print usage"); options.addOption(helpOption); Option reportFileOption = new Option(REPORT_FILE, "reportfile", true, "File name of the test results report"); options.addOption(reportFileOption); return options; } }