Package wyc.testing

Source Code of wyc.testing.TestUtils$StreamGrabber

package wyc.testing;

import static org.junit.Assert.fail;

import java.io.*;

import wyc.WycMain;
import wyc.util.WycBuildTask;
import wycc.util.Pair;

/**
* Provides some simple helper functions used by all test harnesses.
*
* @author David J. Pearce
*
*/
public class TestUtils {

  /**
   * Run the Whiley Compiler with the given list of arguments.
   *
   * @param args
   *            --- list of command-line arguments to provide to the Whiley
   *            Compiler.
   * @return
   */
  public static Pair<Integer,String> compile(String... args) {
    ByteArrayOutputStream syserr = new ByteArrayOutputStream();
    ByteArrayOutputStream sysout = new ByteArrayOutputStream();
    int exitCode = new WycMain(new WycBuildTask(), WycMain.DEFAULT_OPTIONS, sysout, syserr)
        .run(args);
    byte[] errBytes = syserr.toByteArray();
    byte[] outBytes = sysout.toByteArray();
    String output = new String(errBytes) + new String(outBytes);
    return new Pair<Integer,String>(exitCode,output);
  }

  /**
   * Execute a given class file using the "java" command, and return all
   * output written to stdout. In the case of some kind of failure, write the
   * generated stderr stream to this processes stdout.
   *
   * @param classPath
   *            Class path to use when executing Java code. Note, directories
   *            can always be safely separated with '/', and path separated
   *            with ':'.
   * @param srcDir
   *            Path to root of package containing class. Note, directories
   *            can always be safely separated with '/'.
   * @param className
   *            Name of class to execute
   * @param args
   *            Arguments to supply on the command-line.
   * @return All output generated from the class that was written to stdout.
   */
  public static String exec(String classPath, String srcDir, String className, String... args) {
    try {
      classPath = classPath.replace('/', File.separatorChar);
      classPath = classPath.replace(':', File.pathSeparatorChar);
      srcDir = srcDir.replace('/', File.separatorChar);
      String tmp = "java -cp " + classPath + " " + className;
      for (String arg : args) {
        tmp += " " + arg;
      }
      Process p = Runtime.getRuntime().exec(tmp, null, new File(srcDir));

      StringBuffer syserr = new StringBuffer();
      StringBuffer sysout = new StringBuffer();
      new StreamGrabber(p.getErrorStream(), syserr);
      new StreamGrabber(p.getInputStream(), sysout);
      int exitCode = p.waitFor();
      if (exitCode != 0) {
        System.err
            .println("============================================================");
        System.err.println(className);
        System.err
            .println("============================================================");
        System.err.println(syserr);
        return null;
      } else {
        return sysout.toString();
      }
    } catch (Exception ex) {
      ex.printStackTrace();
      fail("Problem running compiled test");
    }

    return null;
  }

  /**
   * Compare the output of executing java on the test case with a reference
   * file. If the output differs from the reference output, then the offending
   * line is written to the stdout and an exception is thrown.
   *
   * @param output
   *            This provides the output from executing java on the test case.
   * @param referenceFile
   *            The full path to the reference file. This should use the
   *            appropriate separator char for the host operating system.
   */
  public static void compare(String output, String referenceFile) {
    try {
      BufferedReader outReader = new BufferedReader(new StringReader(
          output));
      BufferedReader refReader = new BufferedReader(new FileReader(
          new File(referenceFile)));

      while (refReader.ready() && outReader.ready()) {
        String a = refReader.readLine();
        String b = outReader.readLine();

        if (a.equals(b)) {
          continue;
        } else {
          System.err.println(" > " + a);
          System.err.println(" < " + b);
          throw new Error("Output doesn't match reference");
        }
      }

      String l1 = outReader.readLine();
      String l2 = refReader.readLine();
      if (l1 == null && l2 == null)
        return;
      do {
        l1 = outReader.readLine();
        l2 = refReader.readLine();
        if (l1 != null) {
          System.err.println(" < " + l1);
        } else if (l2 != null) {
          System.err.println(" > " + l2);
        }
      } while (l1 != null && l2 != null);

      fail("Files do not match");
    } catch (Exception ex) {
      ex.printStackTrace();
      fail();
    }
  }

  /**
   * Grab everything produced by a given input stream until the End-Of-File
   * (EOF) is reached. This is implemented as a separate thread to ensure that
   * reading from other streams can happen concurrently. For example, we can
   * read concurrently from <code>stdin</code> and <code>stderr</code> for
   * some process without blocking that process.
   *
   * @author David J. Pearce
   *
   */
  static public class StreamGrabber extends Thread {
    private InputStream input;
    private StringBuffer buffer;

    StreamGrabber(InputStream input, StringBuffer buffer) {
      this.input = input;
      this.buffer = buffer;
      start();
    }

    public void run() {
      try {
        int nextChar;
        // keep reading!!
        while ((nextChar = input.read()) != -1) {
          buffer.append((char) nextChar);
        }
      } catch (IOException ioe) {
      }
    }
  }
}
TOP

Related Classes of wyc.testing.TestUtils$StreamGrabber

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.