Search in sources :

Example 1 with BootstrapEvent

use of com.carrotsearch.ant.tasks.junit4.events.BootstrapEvent in project randomizedtesting by randomizedtesting.

the class LocalSlaveStreamHandler method pumpEvents.

/**
   * Pump events from event stream.
   */
void pumpEvents(InputStream eventStream) {
    try {
        Deserializer deserializer = new Deserializer(eventStream, refLoader);
        IEvent event = null;
        while ((event = deserializer.deserialize()) != null) {
            switch(event.getType()) {
                case APPEND_STDERR:
                case APPEND_STDOUT:
                    // Ignore these two on activity heartbeats. GH-117
                    break;
                default:
                    lastActivity = System.currentTimeMillis();
                    break;
            }
            try {
                switch(event.getType()) {
                    case QUIT:
                        eventBus.post(event);
                        return;
                    case IDLE:
                        eventBus.post(new SlaveIdle(stdinWriter));
                        break;
                    case BOOTSTRAP:
                        clientCharset = Charset.forName(((BootstrapEvent) event).getDefaultCharsetName());
                        stdinWriter = new OutputStreamWriter(stdin, clientCharset);
                        eventBus.post(event);
                        break;
                    case APPEND_STDERR:
                    case APPEND_STDOUT:
                        assert streamsBuffer.getFilePointer() == streamsBuffer.length();
                        final long bufferStart = streamsBuffer.getFilePointer();
                        IStreamEvent streamEvent = (IStreamEvent) event;
                        streamEvent.copyTo(streamsBufferWrapper);
                        final long bufferEnd = streamsBuffer.getFilePointer();
                        event = new OnDiskStreamEvent(event.getType(), streamsBuffer, bufferStart, bufferEnd);
                        eventBus.post(event);
                        break;
                    default:
                        eventBus.post(event);
                }
            } catch (Throwable t) {
                warnStream.println("Event bus dispatch error: " + t.toString());
                t.printStackTrace(warnStream);
            }
        }
        lastActivity = null;
    } catch (Throwable e) {
        if (!stopping) {
            warnStream.println("Event stream error: " + e.toString());
            e.printStackTrace(warnStream);
        }
    }
}
Also used : IEvent(com.carrotsearch.ant.tasks.junit4.events.IEvent) IStreamEvent(com.carrotsearch.ant.tasks.junit4.events.IStreamEvent) Deserializer(com.carrotsearch.ant.tasks.junit4.events.Deserializer) BootstrapEvent(com.carrotsearch.ant.tasks.junit4.events.BootstrapEvent) OutputStreamWriter(java.io.OutputStreamWriter)

Example 2 with BootstrapEvent

use of com.carrotsearch.ant.tasks.junit4.events.BootstrapEvent in project randomizedtesting by randomizedtesting.

the class SlaveMain method main.

/**
   * Console entry point.
   */
@SuppressWarnings("resource")
public static void main(String[] allArgs) {
    int exitStatus = 0;
    Serializer serializer = null;
    try {
        final ArrayDeque<String> args = new ArrayDeque<String>(Arrays.asList(allArgs));
        // Options.
        boolean debugStream = false;
        boolean flushFrequently = false;
        File eventsFile = null;
        boolean suitesOnStdin = false;
        List<String> testClasses = new ArrayList<>();
        while (!args.isEmpty()) {
            String option = args.pop();
            if (option.equals(OPTION_FREQUENT_FLUSH)) {
                flushFrequently = true;
            } else if (option.equals(OPTION_STDIN)) {
                suitesOnStdin = true;
            } else if (option.equals(OPTION_SYSOUTS)) {
                multiplexStdStreams = true;
            } else if (option.equals(OPTION_EVENTSFILE)) {
                eventsFile = new File(args.pop());
                if (eventsFile.isFile() && eventsFile.length() > 0) {
                    RandomAccessFile raf = new RandomAccessFile(eventsFile, "rw");
                    raf.setLength(0);
                    raf.close();
                }
            } else if (option.startsWith(OPTION_DEBUGSTREAM)) {
                debugStream = true;
            } else if (option.startsWith("@")) {
                // Append arguments file, one line per option.
                args.addAll(Arrays.asList(readArgsFile(option.substring(1))));
            } else {
                // The default expectation is a test class.
                testClasses.add(option);
            }
        }
        // Set up events channel and events serializer.
        if (eventsFile == null) {
            throw new IOException("You must specify communication channel for events.");
        }
        // Send bootstrap package.
        serializer = new Serializer(new EventsOutputStream(eventsFile)).serialize(new BootstrapEvent()).flush();
        // Redirect original streams and start running tests.
        redirectStreams(serializer, flushFrequently);
        final SlaveMain main = new SlaveMain(serializer);
        main.flushFrequently = flushFrequently;
        main.debugMessagesFile = debugStream ? new File(eventsFile.getAbsolutePath() + ".debug") : null;
        final Iterator<String> stdInput;
        if (suitesOnStdin) {
            stdInput = new StdInLineIterator(main.serializer);
        } else {
            stdInput = Collections.<String>emptyList().iterator();
        }
        main.execute(Iterators.concat(testClasses.iterator(), stdInput));
        // For unhandled exceptions tests.
        if (System.getProperty(SYSPROP_FIRERUNNERFAILURE) != null) {
            throw new Exception(System.getProperty(SYSPROP_FIRERUNNERFAILURE));
        }
    } catch (Throwable t) {
        lastResortMemory = null;
        tryWaitingForGC();
        if (t.getClass() == oomClass) {
            exitStatus = ERR_OOM;
            warn("JVM out of memory.", t);
        } else {
            exitStatus = ERR_EXCEPTION;
            warn("Exception at main loop level.", t);
        }
    }
    try {
        if (serializer != null) {
            try {
                serializer.close();
            } catch (Throwable t) {
                warn("Exception closing serializer.", t);
            }
        }
    } finally {
        JvmExit.halt(exitStatus);
    }
}
Also used : BootstrapEvent(com.carrotsearch.ant.tasks.junit4.events.BootstrapEvent) ArrayList(java.util.ArrayList) IOException(java.io.IOException) ArrayDeque(java.util.ArrayDeque) IOException(java.io.IOException) NoTestsRemainException(org.junit.runner.manipulation.NoTestsRemainException) RandomAccessFile(java.io.RandomAccessFile) RandomAccessFile(java.io.RandomAccessFile) File(java.io.File) Serializer(com.carrotsearch.ant.tasks.junit4.events.Serializer)

Example 3 with BootstrapEvent

use of com.carrotsearch.ant.tasks.junit4.events.BootstrapEvent in project randomizedtesting by randomizedtesting.

the class JUnit4 method executeSlave.

/**
   * Attach listeners and execute a slave process.
   */
private void executeSlave(final ForkedJvmInfo slave, final EventBus aggregatedBus) throws Exception {
    final String uniqueSeed = new SimpleDateFormat("yyyyMMdd_HHmmss_SSS", Locale.ROOT).format(new Date());
    final Path classNamesFile = tempFile(uniqueSeed, "junit4-J" + slave.id, ".suites", getTempDir());
    temporaryFiles.add(classNamesFile);
    final Path classNamesDynamic = tempFile(uniqueSeed, "junit4-J" + slave.id, ".dynamic-suites", getTempDir());
    final Path streamsBufferFile = tempFile(uniqueSeed, "junit4-J" + slave.id, ".spill", getTempDir());
    // Dump all test class names to a temporary file.
    String testClassPerLine = Joiner.on("\n").join(slave.testSuites);
    log("Test class names:\n" + testClassPerLine, Project.MSG_VERBOSE);
    Files.write(classNamesFile, testClassPerLine.getBytes(StandardCharsets.UTF_8));
    // Prepare command line for java execution.
    CommandlineJava commandline;
    commandline = (CommandlineJava) getCommandline().clone();
    commandline.createClasspath(getProject()).add(addSlaveClasspath());
    commandline.setClassname(SlaveMainSafe.class.getName());
    if (slave.slaves == 1) {
        commandline.createArgument().setValue(SlaveMain.OPTION_FREQUENT_FLUSH);
    }
    // Set up full output files.
    Path sysoutFile = tempFile(uniqueSeed, "junit4-J" + slave.id, ".sysout", getTempDir());
    Path syserrFile = tempFile(uniqueSeed, "junit4-J" + slave.id, ".syserr", getTempDir());
    // Set up communication channel.
    Path eventFile = tempFile(uniqueSeed, "junit4-J" + slave.id, ".events", getTempDir());
    temporaryFiles.add(eventFile);
    commandline.createArgument().setValue(SlaveMain.OPTION_EVENTSFILE);
    commandline.createArgument().setFile(eventFile.toFile());
    if (sysouts) {
        commandline.createArgument().setValue(SlaveMain.OPTION_SYSOUTS);
    }
    if (debugStream) {
        commandline.createArgument().setValue(SlaveMain.OPTION_DEBUGSTREAM);
    }
    InputStream eventStream = new TailInputStream(eventFile);
    // Set up input suites file.
    commandline.createArgument().setValue("@" + classNamesFile.toAbsolutePath().normalize());
    // not using it.
    if (dynamicAssignmentRatio > 0) {
        commandline.createArgument().setValue(SlaveMain.OPTION_STDIN);
    }
    final EventBus eventBus = new EventBus("slave-" + slave.id);
    final DiagnosticsListener diagnosticsListener = new DiagnosticsListener(slave, this);
    eventBus.register(diagnosticsListener);
    eventBus.register(new AggregatingListener(aggregatedBus, slave));
    final AtomicReference<Charset> clientCharset = new AtomicReference<Charset>();
    final AtomicBoolean clientWithLimitedCharset = new AtomicBoolean();
    final PrintWriter w = new PrintWriter(Files.newBufferedWriter(classNamesDynamic, StandardCharsets.UTF_8));
    eventBus.register(new Object() {

        @Subscribe
        public void onIdleSlave(final SlaveIdle idleSlave) {
            aggregatedBus.post(new SlaveIdle() {

                @Override
                public void finished() {
                    idleSlave.finished();
                }

                @Override
                public void newSuite(String suiteName) {
                    if (!clientCharset.get().newEncoder().canEncode(suiteName)) {
                        clientWithLimitedCharset.set(true);
                        log("Forked JVM J" + slave.id + " skipped suite (cannot encode suite name in charset " + clientCharset.get() + "): " + suiteName, Project.MSG_WARN);
                        return;
                    }
                    log("Forked JVM J" + slave.id + " stole suite: " + suiteName, Project.MSG_VERBOSE);
                    w.println(suiteName);
                    w.flush();
                    idleSlave.newSuite(suiteName);
                }
            });
        }

        @Subscribe
        public void onBootstrap(final BootstrapEvent e) {
            Charset cs = Charset.forName(((BootstrapEvent) e).getDefaultCharsetName());
            clientCharset.set(cs);
            slave.start = System.currentTimeMillis();
            slave.setBootstrapEvent(e);
            aggregatedBus.post(new ChildBootstrap(slave));
        }

        @Subscribe
        public void receiveQuit(QuitEvent e) {
            slave.end = System.currentTimeMillis();
        }
    });
    Closer closer = Closer.create();
    closer.register(eventStream);
    closer.register(w);
    try {
        OutputStream sysout = closer.register(new BufferedOutputStream(Files.newOutputStream(sysoutFile)));
        OutputStream syserr = closer.register(new BufferedOutputStream(Files.newOutputStream(syserrFile)));
        RandomAccessFile streamsBuffer = closer.register(new RandomAccessFile(streamsBufferFile.toFile(), "rw"));
        Execute execute = forkProcess(slave, eventBus, commandline, eventStream, sysout, syserr, streamsBuffer);
        log("Forked JVM J" + slave.id + " finished with exit code: " + execute.getExitValue(), Project.MSG_DEBUG);
        if (execute.isFailure()) {
            final int exitStatus = execute.getExitValue();
            switch(exitStatus) {
                case SlaveMain.ERR_NO_JUNIT:
                    throw new BuildException("Forked JVM's classpath must include a junit4 JAR.");
                case SlaveMain.ERR_OLD_JUNIT:
                    throw new BuildException("Forked JVM's classpath must use JUnit 4.10 or newer.");
                default:
                    Closeables.close(sysout, false);
                    Closeables.close(syserr, false);
                    StringBuilder message = new StringBuilder();
                    if (exitStatus == SlaveMain.ERR_OOM) {
                        message.append("Forked JVM ran out of memory.");
                    } else {
                        message.append("Forked process returned with error code: ").append(exitStatus).append(".");
                    }
                    if (Files.size(sysoutFile) > 0 || Files.size(syserrFile) > 0) {
                        if (exitStatus != SlaveMain.ERR_OOM) {
                            message.append(" Very likely a JVM crash. ");
                        }
                        if (jvmOutputAction.contains(JvmOutputAction.PIPE)) {
                            message.append(" Process output piped in logs above.");
                        } else if (!jvmOutputAction.contains(JvmOutputAction.IGNORE)) {
                            if (Files.size(sysoutFile) > 0) {
                                message.append(" See process stdout at: " + sysoutFile.toAbsolutePath());
                            }
                            if (Files.size(syserrFile) > 0) {
                                message.append(" See process stderr at: " + syserrFile.toAbsolutePath());
                            }
                        }
                    }
                    throw new BuildException(message.toString());
            }
        }
    } catch (Throwable t) {
        throw closer.rethrow(t);
    } finally {
        try {
            closer.close();
        } finally {
            com.google.common.io.Files.asByteSource(classNamesDynamic.toFile()).copyTo(com.google.common.io.Files.asByteSink(classNamesFile.toFile(), FileWriteMode.APPEND));
            Files.delete(classNamesDynamic);
            Files.delete(streamsBufferFile);
            // Check sysout/syserr lengths.
            checkJvmOutput(aggregatedBus, sysoutFile, slave, "stdout");
            checkJvmOutput(aggregatedBus, syserrFile, slave, "stderr");
        }
    }
    if (!diagnosticsListener.quitReceived()) {
        throw new BuildException("Quit event not received from the forked process? This may indicate JVM crash or runner bugs.");
    }
    if (clientWithLimitedCharset.get() && dynamicAssignmentRatio > 0) {
        throw new BuildException("Forked JVM J" + slave.id + " was not be able to decode class names when using" + " charset: " + clientCharset + ". Do not use " + "dynamic suite balancing to work around this problem (-DdynamicAssignmentRatio=0).");
    }
}
Also used : Execute(org.apache.tools.ant.taskdefs.Execute) BufferedOutputStream(java.io.BufferedOutputStream) TeeOutputStream(com.carrotsearch.randomizedtesting.TeeOutputStream) OutputStream(java.io.OutputStream) EventBus(com.google.common.eventbus.EventBus) Subscribe(com.google.common.eventbus.Subscribe) BufferedOutputStream(java.io.BufferedOutputStream) AggregatingListener(com.carrotsearch.ant.tasks.junit4.events.aggregated.AggregatingListener) PrintWriter(java.io.PrintWriter) AggregatedQuitEvent(com.carrotsearch.ant.tasks.junit4.events.aggregated.AggregatedQuitEvent) QuitEvent(com.carrotsearch.ant.tasks.junit4.events.QuitEvent) Path(java.nio.file.Path) Closer(com.google.common.io.Closer) BufferedInputStream(java.io.BufferedInputStream) InputStream(java.io.InputStream) BootstrapEvent(com.carrotsearch.ant.tasks.junit4.events.BootstrapEvent) Charset(java.nio.charset.Charset) AtomicReference(java.util.concurrent.atomic.AtomicReference) CommandlineJava(org.apache.tools.ant.types.CommandlineJava) Date(java.util.Date) SuiteHint(com.carrotsearch.ant.tasks.junit4.balancers.SuiteHint) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) ChildBootstrap(com.carrotsearch.ant.tasks.junit4.events.aggregated.ChildBootstrap) RandomAccessFile(java.io.RandomAccessFile) SlaveMainSafe(com.carrotsearch.ant.tasks.junit4.slave.SlaveMainSafe) BuildException(org.apache.tools.ant.BuildException) SimpleDateFormat(java.text.SimpleDateFormat)

Aggregations

BootstrapEvent (com.carrotsearch.ant.tasks.junit4.events.BootstrapEvent)3 RandomAccessFile (java.io.RandomAccessFile)2 SuiteHint (com.carrotsearch.ant.tasks.junit4.balancers.SuiteHint)1 Deserializer (com.carrotsearch.ant.tasks.junit4.events.Deserializer)1 IEvent (com.carrotsearch.ant.tasks.junit4.events.IEvent)1 IStreamEvent (com.carrotsearch.ant.tasks.junit4.events.IStreamEvent)1 QuitEvent (com.carrotsearch.ant.tasks.junit4.events.QuitEvent)1 Serializer (com.carrotsearch.ant.tasks.junit4.events.Serializer)1 AggregatedQuitEvent (com.carrotsearch.ant.tasks.junit4.events.aggregated.AggregatedQuitEvent)1 AggregatingListener (com.carrotsearch.ant.tasks.junit4.events.aggregated.AggregatingListener)1 ChildBootstrap (com.carrotsearch.ant.tasks.junit4.events.aggregated.ChildBootstrap)1 SlaveMainSafe (com.carrotsearch.ant.tasks.junit4.slave.SlaveMainSafe)1 TeeOutputStream (com.carrotsearch.randomizedtesting.TeeOutputStream)1 EventBus (com.google.common.eventbus.EventBus)1 Subscribe (com.google.common.eventbus.Subscribe)1 Closer (com.google.common.io.Closer)1 BufferedInputStream (java.io.BufferedInputStream)1 BufferedOutputStream (java.io.BufferedOutputStream)1 File (java.io.File)1 IOException (java.io.IOException)1