/**
   * Executes the passed in test case. Instrumentation is added according to the name of the file as
   * explained in {@link #createTests(Class)}. Note that this code is not generalizable.
   */
  @Override
  protected void runChild(InstrumentTestCase testCase, RunNotifier notifier) {
    // TODO Current tests are hard-coded, automate this eventually
    notifier.fireTestStarted(testCase.name);

    ByteArrayOutputStream out = new ByteArrayOutputStream();
    PrintStream ps = new PrintStream(out);

    PolyglotEngine vm = null;
    try {
      // We use the name of the file to determine what visitor to attach to it.
      if (testCase.baseName.endsWith(ASSIGNMENT_VALUE_SUFFIX)) {
        // Set up the execution context for Simple and register our two listeners
        vm =
            PolyglotEngine.newBuilder()
                .setIn(new ByteArrayInputStream(testCase.testInput.getBytes("UTF-8")))
                .setOut(out)
                .build();

        final String src = readAllLines(testCase.path);
        vm.eval(Source.fromText(src, testCase.path.toString()).withMimeType("application/x-sl"));

        PolyglotEngine.Value main = vm.findGlobalSymbol("main");
        main.execute();
      } else {
        notifier.fireTestFailure(
            new Failure(
                testCase.name, new UnsupportedOperationException("No instrumentation found.")));
      }
      ps.flush();
      String actualOutput = new String(out.toByteArray());
      Assert.assertEquals(testCase.expectedOutput, actualOutput);
    } catch (Throwable ex) {
      notifier.fireTestFailure(new Failure(testCase.name, ex));
    } finally {
      if (vm != null) {
        vm.dispose();
      }
      notifier.fireTestFinished(testCase.name);
    }
  }
示例#2
0
  /**
   * The read-eval-print loop, which can take input from a console, command line expression or a
   * file. There are two ways the repl can terminate:
   *
   * <ol>
   *   <li>A {@code quit} command is executed successfully, which case the system exits from the
   *       {@link Quit} {@code .Internal} .
   *   <li>EOF on the input.
   * </ol>
   *
   * In case 2, we must implicitly execute a {@code quit("default, 0L, TRUE} command before exiting.
   * So,in either case, we never return.
   */
  static int readEvalPrint(PolyglotEngine vm) {
    int lastStatus = 0;
    ContextInfo contextInfo = ContextInfo.getContextInfo(vm);
    ConsoleHandler consoleHandler = contextInfo.getConsoleHandler();
    try {
      // console.println("initialize time: " + (System.currentTimeMillis() - start));
      REPL:
      for (; ; ) {
        boolean doEcho = doEcho(vm);
        consoleHandler.setPrompt(doEcho ? "> " : null);
        try {
          String input = consoleHandler.readLine();
          if (input == null) {
            throw new EOFException();
          }
          String trInput = input.trim();
          if (trInput.equals("") || trInput.charAt(0) == '#') {
            // nothing to parse
            continue;
          }

          String continuePrompt = getContinuePrompt();
          StringBuffer sb = new StringBuffer(input);
          Source source = RSource.fromTextInternal(sb.toString(), RSource.Internal.SHELL_INPUT);
          while (true) {
            lastStatus = 0;
            try {
              try {
                vm.eval(source);
                // checked exceptions are wrapped in RuntimeExceptions
              } catch (RuntimeException e) {
                if (e.getCause() instanceof com.oracle.truffle.api.vm.IncompleteSourceException) {
                  throw e.getCause().getCause();
                }
                throw e;
              }
            } catch (IncompleteSourceException e) {
              // read another line of input
              consoleHandler.setPrompt(doEcho ? continuePrompt : null);
              String additionalInput = consoleHandler.readLine();
              if (additionalInput == null) {
                throw new EOFException();
              }
              sb.append(additionalInput);
              source = RSource.fromTextInternal(sb.toString(), RSource.Internal.SHELL_INPUT);
              // The only continuation in the while loop
              continue;
            } catch (ParseException e) {
              e.report(consoleHandler);
              lastStatus = 1;
            } catch (RError e) {
              // drop through to continue REPL and remember last eval was an error
              lastStatus = 1;
            } catch (JumpToTopLevelException e) {
              // drop through to continue REPL
            } catch (DebugExitException e) {
              throw (RuntimeException) e.getCause();
            } catch (ExitException e) {
              // usually from quit
              int status = e.getStatus();
              if (contextInfo.getParent() == null) {
                vm.dispose();
                Utils.systemExit(status);
              } else {
                return status;
              }
            } catch (Throwable e) {
              RInternalError.reportErrorAndConsoleLog(e, consoleHandler, 0);
              // We continue the repl even though the system may be broken
              lastStatus = 1;
            }
            continue REPL;
          }
        } catch (UserInterruptException e) {
          // interrupted by ctrl-c
        }
      }
    } catch (JumpToTopLevelException | EOFException ex) {
      // JumpToTopLevelException can happen if user profile invokes browser (unlikely but
      // possible)
      try {
        vm.eval(QUIT_EOF);
      } catch (JumpToTopLevelException e) {
        Utils.systemExit(0);
      } catch (ExitException e) {
        // normal quit, but with exit code based on lastStatus
        if (contextInfo.getParent() == null) {
          Utils.systemExit(lastStatus);
        } else {
          return lastStatus;
        }
      } catch (Throwable e) {
        throw RInternalError.shouldNotReachHere(e);
      }
    } finally {
      vm.dispose();
    }
    return 0;
  }