Package org.rascalmpl.test.infrastructure

Source Code of org.rascalmpl.test.infrastructure.ConcurrentTestFramework$ForkedRunnable

/*******************************************************************************
* Copyright (c) 2009-2013 CWI
* 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:

*   * Jurgen J. Vinju - Jurgen.Vinju@cwi.nl - CWI
*   * Tijs van der Storm - Tijs.van.der.Storm@cwi.nl
*   * Emilie Balland - (CWI)
*   * Anya Helene Bagge - (UiB)
*   * Paul Klint - Paul.Klint@cwi.nl - CWI
*   * Mark Hills - Mark.Hills@cwi.nl (CWI)
*   * Arnold Lankamp - Arnold.Lankamp@cwi.nl
*   * Davy Landman - Davy.Landman@cwi.nl
*******************************************************************************/
package org.rascalmpl.test.infrastructure;

import static org.junit.Assert.assertTrue;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.URI;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.imp.pdb.facts.IBool;
import org.eclipse.imp.pdb.facts.IValue;
import org.eclipse.imp.pdb.facts.exceptions.FactTypeUseException;
import org.eclipse.imp.pdb.facts.type.TypeFactory;
import org.junit.After;
import org.rascalmpl.interpreter.Evaluator;
import org.rascalmpl.interpreter.env.GlobalEnvironment;
import org.rascalmpl.interpreter.env.ModuleEnvironment;
import org.rascalmpl.interpreter.result.Result;
import org.rascalmpl.interpreter.staticErrors.StaticError;
import org.rascalmpl.uri.ClassResourceInput;
import org.rascalmpl.uri.IURIInputStreamResolver;
import org.rascalmpl.uri.URIResolverRegistry;
import org.rascalmpl.uri.URIUtil;
import org.rascalmpl.values.ValueFactoryFactory;


public class ConcurrentTestFramework {
  private final static int N = 12;
  private final static Evaluator evaluator;
  private Evaluator[] evaluators = null;
  private final static TestModuleResolver modules;

  private final static PrintWriter stderr;
  private final static PrintWriter stdout;

  /**
   * This class allows us to load modules from string values.
   */
  private static class TestModuleResolver implements IURIInputStreamResolver {
    private Map<String,String> modules = new HashMap<String,String>();

    public void addModule(String name, String contents) {
      name = name.replaceAll("::", "/");
      if (!name.startsWith("/")) {
        name = "/" + name;
      }
      if (!name.endsWith(".rsc")) {
        name = name + ".rsc";
      }
      modules.put(name, contents);
    }

    @Override
    public boolean exists(URI uri) {
      return modules.containsKey(uri.getPath());
    }

    @Override
    public InputStream getInputStream(URI uri) throws IOException {
      String contents = modules.get(uri.getPath());
      if (contents != null) {
        return new ByteArrayInputStream(contents.getBytes());
      }
      return null;
    }

    public void reset(){
      modules = new HashMap<String,String>();
    }

    @Override
    public String scheme() {
      return "test-modules";
    }

    @Override
    public boolean isDirectory(URI uri) {
      return false;
    }

    @Override
    public boolean isFile(URI uri) {
      return false;
    }

    @Override
    public long lastModified(URI uri) {
      return 0;
    }

    @Override
    public String[] listEntries(URI uri) {
      return null;
    }

    @Override
    public boolean supportsHost() {
      return false;
    }

    @Override
    public Charset getCharset(URI uri) throws IOException {
      return null;
    }
  }

  static{
    GlobalEnvironment heap = new GlobalEnvironment();
    ModuleEnvironment root = heap.addModule(new ModuleEnvironment("___test___", heap));
    modules = new TestModuleResolver();

    stderr = new PrintWriter(System.err);
    stdout = new PrintWriter(System.out);
    evaluator = new Evaluator(ValueFactoryFactory.getValueFactory(), stderr, stdout,  root, heap);
    URIResolverRegistry resolverRegistry = evaluator.getResolverRegistry();

    evaluator.addRascalSearchPath(URIUtil.rootScheme("test-modules"));
    resolverRegistry.registerInput(modules);

    evaluator.addRascalSearchPath(URIUtil.rootScheme("benchmarks"));
    resolverRegistry.registerInput(new ClassResourceInput(resolverRegistry, "benchmarks", Evaluator.class, "/org/rascalmpl/benchmark"));

  }

  public ConcurrentTestFramework() {
    super();
  }

  private void reset() {
    evaluator.getHeap().clear();
    evaluator.__getRootScope().reset();
    modules.reset();
    evaluators = null;
    evaluator.getAccumulators().clear();
  }

  private void forkEvaluators() {
    evaluator.freeze();
    evaluators = new Evaluator[N];
    synchronized(evaluators) {
      evaluators[0] = evaluator;
      for(int i = 1; i < evaluators.length; i++) {
        evaluators[i]= (Evaluator) evaluator.fork();
      }
    }
  }

  @After
  public void assureEvaluatorIsSane() {
    assertTrue(evaluator.getCurrentEnvt().isRootScope());
    assertTrue(evaluator.getCurrentEnvt().isRootStackFrame());
    assertTrue("When we are at the root scope and stack frame, the accumulators should be empty as well", evaluator.getAccumulators().empty());
    for(int i = 0; i < evaluators.length; i++) {
      assertTrue(evaluators[i].getCurrentEnvt().isRootScope());
      assertTrue(evaluators[i].getCurrentEnvt().isRootStackFrame());
      assertTrue("When we are at the root scope and stack frame, the accumulators should be empty as well", evaluators[i].getAccumulators().empty());
    }
  }

  public boolean runTest(String command) {
    reset();
    forkEvaluators();
    return executeInThreads(command);
  }

  public boolean runRascalTests(final String command) {
    try {
      reset();
      forkEvaluators();
      return runConcurrently(new ForkedRunnable() {
        @Override
        public boolean run(Evaluator eval) {
          execute(command, eval);
          return eval.runTests(eval.getMonitor());
        }
      });
    }
    finally {
      stderr.flush();
      stdout.flush();
    }
  }

  public boolean runTestInSameEvaluator(String command) {
    if(evaluators == null) {
      forkEvaluators();
    }
    return executeInThreads(command);
  }

  public boolean runTest(String command1, String command2) {
    reset();
    execute(command1, evaluator);
    return executeInThreads(command2);
  }

  public ConcurrentTestFramework prepare(String command) {
    try {
      reset();
      execute(command, evaluator);
    }
    catch (StaticError e) {
      throw e;
    }
    catch (Exception e) {
      System.err.println("Unhandled exception while preparing test: " + e);
      e.printStackTrace();
      throw new AssertionError(e.getMessage());
    }
    return this;
  }

  public ConcurrentTestFramework prepareMore(String command) {
    try {
      execute(command, evaluator);

    }
    catch (StaticError e) {
      throw e;
    }
    catch (Exception e) {
      System.err.println("Unhandled exception while preparing test: " + e);
      throw new AssertionError(e.getMessage());
    }
    return this;
  }

  public boolean prepareModule(String name, String module) throws FactTypeUseException {
    reset();
    modules.addModule(name, module);
    return true;
  }

  private boolean execute(String command, Evaluator eval){
    Result<IValue> result = eval.eval(null, command, URIUtil.rootScheme("stdin"));

    if (result.getType().isBottom()) {
      return true;

    }
    if (result.getValue() == null) {
      return false;
    }

    if (result.getType() == TypeFactory.getInstance().boolType()) {
      return ((IBool) result.getValue()).getValue();
    }

    return false;
  }

  private boolean executeInThreads(final String command){
    return runConcurrently(new ForkedRunnable() {
      @Override
      public boolean run(Evaluator eval) {
        Result<IValue> result = eval.eval(null, command, URIUtil.rootScheme("stdin"));

        if (result.getType().isBottom()) {
          return true;

        }
        if (result.getValue() == null) {
          return false;
        }

        if (result.getType() == TypeFactory.getInstance().boolType()) {
          return ((IBool) result.getValue()).getValue();
        }
        return false;
      }});
  }

  boolean runConcurrently(final ForkedRunnable runner) {
    final RuntimeException failure = new RuntimeException();
    final RuntimeException[] results = new RuntimeException[N];
    final Thread[] threads = new Thread[N];

    for(int i = 0; i < N; i++) {
      final int threadNumber = i;
      threads[i] = new Thread(new Runnable() {
        @Override
        public void run() {
          Evaluator eval;
          synchronized(evaluators) {
            eval = evaluators[threadNumber];
          }
          try {
            boolean result = runner.run(eval);
            synchronized(results) {
              results[threadNumber] = result ? null : failure;
            }
          }
          catch(RuntimeException e) {
            synchronized(results) {
              results[threadNumber] = e;
            }
          }
          // System.err.println(threadNumber + ": " + System.identityHashCode(eval.hashCode()) + ", " + System.identityHashCode(eval.getAccumulators()));
        }     
      });
      threads[i].start();
    }
    for(int i = 0; i < N; i++) {
      try {
        threads[i].join();
      } catch (InterruptedException e) {
        throw new RuntimeException("Thread interrupted", e);
      }
    }
    synchronized(results) {
      for(int i = 0; i < N; i++) {
        if(results[i] == failure) {
          return false;
        }
        else if(results[i] != null) {
          throw results[i];
        }
      }
    }
    return true;

  }

  interface ForkedRunnable {
    boolean run(Evaluator eval);
  }
}
TOP

Related Classes of org.rascalmpl.test.infrastructure.ConcurrentTestFramework$ForkedRunnable

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.