--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VTT Technical Research Centre of Finland - initial API and implementation
+ *******************************************************************************/
+package org.simantics.db.testing.base;
+
+import gnu.trove.list.array.TLongArrayList;
+
+import org.apache.commons.math3.stat.regression.SimpleRegression;
+import org.junit.Test;
+import org.simantics.db.Session;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.testing.cases.FreshDatabaseTest;
+import org.simantics.db.testing.common.Command;
+import org.simantics.db.testing.common.CommandSequenceEnvironment;
+import org.simantics.db.testing.common.CommandSpec;
+
+
+/**
+ *
+ * @author Antti Villberg <antti.villberg@semantum.fi>
+ *
+ */
+abstract public class CommandSequenceTest extends FreshDatabaseTest implements CommandSequenceEnvironment {
+
+ private static final boolean TRACE = true;
+
+ protected TLongArrayList executionTimes = new TLongArrayList();
+
+ protected double getSlowdown() {
+
+ SimpleRegression regression = new SimpleRegression();
+ for(int i=0;i<executionTimes.size();i++) {
+ regression.addData(i, executionTimes.getQuick(i));
+ }
+ double intercept = regression.getIntercept();
+ double slope = regression.getSlope();
+
+ return (slope * executionTimes.size())/Math.abs(intercept);
+
+ }
+
+ protected String getExecutionData() {
+ StringBuilder b = new StringBuilder();
+ for(int i=0;i<executionTimes.size();i++) {
+ b.append(executionTimes.get(i) + "\n");
+ }
+ return b.toString();
+ }
+
+ protected void printExecutionTimes() {
+ for(int i=0;i<executionTimes.size();i++) {
+ System.err.println("" + i + ": " + executionTimes.getQuick(i));
+ }
+ }
+
+ protected void assertSlowdown(double slowdown) {
+ assertLess(getSlowdown(), 0.1, getExecutionData());
+ }
+
+ protected int getSequenceSize() {
+ return 0;
+ }
+
+ protected Command[] beforeSequence(CommandSequenceEnvironment environment) throws Exception {
+ return new Command[0];
+ }
+
+ protected Command[] afterSequence(CommandSequenceEnvironment environment) throws Exception {
+ return new Command[0];
+ }
+
+ protected CommandSpec<?>[] getFactories() {
+ return null;
+ }
+
+ @Override
+ public Session getSession() {
+ return super.getSession();
+ }
+
+ public int randomNatural() {
+ return (int)(Math.random() * Integer.MAX_VALUE);
+ }
+
+ protected Command[] newSequence() throws Exception {
+ int size = getSequenceSize();
+ CommandSpec<?>[] classes = getFactories();
+ int index = 0;
+ Command[] result = new Command[size];
+ double totalWeight = 0;
+ for(CommandSpec<?> p : classes) totalWeight += p.weight;
+ double[] wts = new double[classes.length];
+ index=0;
+ double previous = 0;
+ for(CommandSpec<?> p : classes) {
+ double weight = p.weight/totalWeight;
+ wts[index++] = previous + weight;
+ previous += weight;
+ }
+
+ for(int i=0;i<size;i++) {
+ double n = Math.random();
+ for(int j=0;j<classes.length;j++) {
+ if(n < wts[j]) {
+ result[i] = classes[j].clazz.newInstance();
+ break;
+ }
+ if(j==result.length-1) {
+ result[i] = classes[result.length-1].clazz.newInstance();
+ break;
+ }
+ }
+ }
+ return result;
+ }
+
+ protected CommandSequenceEnvironment createEnvironment() {
+ return this;
+ }
+
+ protected void initialize(CommandSequenceEnvironment environment) throws Exception {
+
+ }
+
+ protected void analyse(CommandSequenceEnvironment environment) throws Exception {
+
+ }
+
+ @Test
+ public void test() throws Exception {
+
+ CommandSequenceEnvironment environment = createEnvironment();
+
+ initialize(environment);
+
+ for(Command command : beforeSequence(environment)) {
+ command.run(environment);
+ }
+
+ int counter=0;
+ int lastProgress=0;
+
+ Command[] sequence = newSequence();
+ for(Command command : sequence) {
+ if (TRACE)
+ System.err.println("[" + counter + "/" + sequence.length + "]: " + command.getClass().getSimpleName());
+ long start = System.nanoTime();
+ try {
+ command.run(environment);
+ } catch (Throwable t) {
+ if(!isAllowed(t)) {
+ throw new AssertionError(t);
+ }
+ }
+ long duration = System.nanoTime() - start;
+ executionTimes.add(duration);
+ int progress = 100*(counter++) / sequence.length;
+ if(progress > lastProgress) {
+ System.err.println("[" + counter + "/" + sequence.length + "]: " + progress + "%");
+ lastProgress = progress;
+ }
+ }
+
+ for(Command command : afterSequence(environment)) {
+ command.run(environment);
+ }
+
+ analyse(environment);
+
+ }
+
+ public void invoke(CommandSequenceEnvironment environment, Command command) {
+ try {
+ command.run(environment);
+ } catch (Throwable t) {
+ if(!isAllowed(t)) {
+ throw new AssertionError(t);
+ }
+ }
+ }
+
+ boolean isAllowed(Throwable t) {
+ if(t instanceof AllowedThrowable) return true;
+ if(t instanceof DatabaseException) {
+ DatabaseException d = (DatabaseException)t;
+ if(d.getCause() instanceof AllowedThrowable) return true;
+ }
+ return false;
+ }
+
+}