/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2010 Oracle and/or its affiliates. All rights reserved.
*
* Oracle and Java are registered trademarks of Oracle and/or its affiliates.
* Other names may be trademarks of their respective owners.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common
* Development and Distribution License("CDDL") (collectively, the
* "License"). You may not use this file except in compliance with the
* License. You can obtain a copy of the License at
* http://www.netbeans.org/cddl-gplv2.html
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
* specific language governing permissions and limitations under the
* License. When distributing the software, include this License Header
* Notice in each file and include the License file at
* nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the
* License Header, with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* If you wish your version of this file to be governed by only the CDDL
* or only the GPL Version 2, indicate your decision by adding
* "[Contributor] elects to include this software in this distribution
* under the [CDDL or GPL Version 2] license." If you do not indicate a
* single choice of license, a recipient has the option to distribute
* your version of this file under either the CDDL, the GPL Version 2 or
* to extend the choice of license to its licensees as provided above.
* However, if you add GPL Version 2 code and therefore, elected the GPL
* Version 2 license, then the option applies only if the new code is
* made subject to such option by the copyright holder.
*
* Contributor(s):
*
* Portions Copyrighted 2008 Sun Microsystems, Inc.
*/
package org.netbeans.modules.ruby.testrunner.ui;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.netbeans.modules.gsf.testrunner.api.Manager;
import org.netbeans.modules.gsf.testrunner.api.TestSession;
import org.netbeans.modules.gsf.testrunner.api.TestSuite;
import org.netbeans.modules.gsf.testrunner.api.Testcase;
import org.netbeans.modules.gsf.testrunner.api.Trouble;
import org.netbeans.modules.ruby.rubyproject.spi.TestRunner.TestType;
import org.netbeans.modules.ruby.testrunner.TestRunnerUtilities;
import org.openide.util.NbBundle;
/**
* An output recognizer for parsing output of the test/unit runner script,
* <code>nb_test_mediator.rb</code>. Updates the test result UI.
*
* @author Erno Mononen
*/
public class TestUnitHandlerFactory implements TestHandlerFactory {
private static final Logger LOGGER = Logger.getLogger(TestUnitHandlerFactory.class.getName());
public boolean printSummary() {
return true;
}
public List<TestRecognizerHandler> createHandlers() {
List<TestRecognizerHandler> result = new ArrayList<TestRecognizerHandler>();
result.add(new SuiteStartingHandler());
result.add(new SuiteStartedHandler());
result.add(new SuiteFinishedHandler());
result.add(new SuiteErrorOutputHandler());
result.add(new ShouldaTestStartedHandler());
result.add(new ShouldaTestFailedHandler());
result.add(new ShouldaTestErrorHandler());
result.add(new TestStartedHandler());
result.add(new TestFailedHandler());
result.add(new TestErrorHandler());
result.add(new ShouldaTestFinishedHandler());
result.add(new TestFinishedHandler());
result.add(new TestLoggerHandler());
result.add(new TestMiscHandler());
result.add(new SuiteMiscHandler());
return result;
}
private static String errorMsg(long failureCount) {
return NbBundle.getMessage(TestUnitHandlerFactory.class, "MSG_Error", failureCount);
}
private static String failureMsg(long failureCount) {
return NbBundle.getMessage(TestUnitHandlerFactory.class, "MSG_Failure", failureCount);
}
static String[] getStackTrace(String message, String stackTrace) {
List<String> stackTraceList = new ArrayList<String>();
stackTraceList.add(message);
for (String location : stackTrace.split("%BR%")) { //NOI18N
if (!TestRunnerUtilities.filterOutFromStacktrace(location)) {
stackTraceList.add(location);
}
}
return stackTraceList.toArray(new String[stackTraceList.size()]);
}
static class TestFailedHandler extends TestRecognizerHandler {
private List<String> output;
public TestFailedHandler(String regex) {
super(regex);
}
public TestFailedHandler() {
super("%TEST_FAILED%\\stime=(.+)\\stestname=(.+)\\((.+)\\)\\smessage=(.*)\\slocation=(.*)"); //NOI18N
}
@Override
void updateUI( Manager manager, TestSession session) {
Testcase testcase = new Testcase(matcher.group(2), TestType.TEST_UNIT.name(), session);
testcase.setTimeMillis(toMillis(matcher.group(1)));
testcase.setClassName(matcher.group(3));
testcase.setTrouble(new Trouble(false));
String message = matcher.group(4);
testcase.getTrouble().setComparisonFailure(getComparisonFailure(message));
String location = matcher.group(5);
testcase.getTrouble().setStackTrace(getStackTrace(message, location));
session.addTestCase(testcase);
String failureMsg = failureMsg(session.incrementFailuresCount());
String testCase = testcase.getName() + "(" + testcase.getClassName() + "):";
output = new ArrayList<String>();
output.add("");
output.add(failureMsg);
output.add(testCase);
output.addAll(Arrays.asList(testcase.getTrouble().getStackTrace()));
output.add("");
manager.displayOutput(session, "", false);
manager.displayOutput(session, failureMsg, false);
manager.displayOutput(session, testCase, false); //NOI18N
for (String line : testcase.getTrouble().getStackTrace()) {
manager.displayOutput(session, line, false);
}
manager.displayOutput(session, "", false);
testcase.addOutputLines(output);
}
@Override
List<String> getRecognizedOutput() {
return new ArrayList<String>(output);
}
}
/**
* Support for Shoulda tests -- see #150613
*/
static class ShouldaTestFailedHandler extends TestFailedHandler {
public ShouldaTestFailedHandler() {
super("%TEST_FAILED%\\stime=(.+)\\stestname=test:\\s(.*)\\.\\s\\((.+)\\)\\smessage=(.*)\\slocation=(.*)"); //NOI18N
}
}
static class TestErrorHandler extends TestRecognizerHandler {
private List<String> output;
public TestErrorHandler() {
this("%TEST_ERROR%\\stime=(.+)\\stestname=(.+)\\((.+)\\)\\smessage=(.*)\\slocation=(.*)"); //NOI18N
}
public TestErrorHandler(String regex) {
super(regex); //NOI18N
}
@Override
void updateUI( Manager manager, TestSession session) {
Testcase testcase = new Testcase(matcher.group(2), TestType.TEST_UNIT.name(), session);
testcase.setTimeMillis(toMillis(matcher.group(1)));
testcase.setClassName(matcher.group(3));
testcase.setTrouble(new Trouble(true));
testcase.getTrouble().setStackTrace(getStackTrace(matcher.group(4), matcher.group(5)));
session.addTestCase(testcase);
String errorMsg = errorMsg(session.incrementFailuresCount());
String testCase = testcase.getName() + "(" + testcase.getClassName() + "):";
output = new ArrayList<String>();
output.add("");
output.add(errorMsg);
output.add(testCase);
output.addAll(Arrays.asList(testcase.getTrouble().getStackTrace()));
output.add("");
manager.displayOutput(session, "", false);
manager.displayOutput(session, errorMsg, false);
manager.displayOutput(session, testCase, false); //NOI18N
for (String line : testcase.getTrouble().getStackTrace()) {
manager.displayOutput(session, line, true);
}
manager.displayOutput(session, "", false);
testcase.addOutputLines(output);
}
@Override
List<String> getRecognizedOutput() {
return new ArrayList<String>(output);
}
}
static class TestStartedHandler extends TestRecognizerHandler {
public TestStartedHandler() {
super("%TEST_STARTED%\\s(.+)\\((.+)\\)"); //NOI18N
}
@Override
void updateUI( Manager manager, TestSession session) {
}
}
/**
* Support for Shoulda tests -- see #150613
*/
static class ShouldaTestStartedHandler extends TestRecognizerHandler {
public ShouldaTestStartedHandler() {
super("%TEST_STARTED%\\stest:\\s(.*)\\.\\s\\((.+)\\)"); //NOI18N
}
@Override
void updateUI( Manager manager, TestSession session) {
}
}
static class TestFinishedHandler extends TestRecognizerHandler {
public TestFinishedHandler(String regex) {
super(regex);
}
public TestFinishedHandler() {
super("%TEST_FINISHED%\\stime=(.+)\\s(.+)\\((.+)\\)"); //NOI18N
}
@Override
void updateUI( Manager manager, TestSession session) {
Testcase testcase = new Testcase(matcher.group(2), TestType.TEST_UNIT.name(), session);
testcase.setTimeMillis(toMillis(matcher.group(1)));
testcase.setClassName(matcher.group(3));
session.addTestCase(testcase);
}
}
/**
* Support for Shoulda tests -- see #150613
*/
static class ShouldaTestFinishedHandler extends TestFinishedHandler {
public ShouldaTestFinishedHandler() {
super("%TEST_FINISHED%\\stime=(.+)\\stest:\\s(.*)\\.\\s\\((.+)\\)"); //NOI18N
}
}
/**
* Support for Shoulda tests -- see #150613
*/
static class ShouldaTestErrorHandler extends TestErrorHandler {
public ShouldaTestErrorHandler() {
super("%TEST_ERROR%\\stime=(.+)\\stestname=test:\\s(.+)\\.\\s\\((.+)\\)\\smessage=(.*)\\slocation=(.*)"); //NOI18N
}
}
/**
* Captures the rest of %TEST_* patterns that are not handled
* otherwise (yet).
*/
static class TestMiscHandler extends TestRecognizerHandler {
public TestMiscHandler() {
super("%TEST_.*"); //NOI18N
}
@Override
void updateUI( Manager manager, TestSession session) {
}
}
static class SuiteFinishedHandler extends TestRecognizerHandler {
public SuiteFinishedHandler() {
super("%SUITE_FINISHED%\\stime=(.+)"); //NOI18N
}
@Override
void updateUI( Manager manager, TestSession session) {
manager.displayReport(session, session.getReport(toMillis(matcher.group(1))));
}
}
static class SuiteStartedHandler extends TestRecognizerHandler {
public SuiteStartedHandler() {
super("%SUITE_STARTED%\\s.*"); //NOI18N
}
@Override
void updateUI( Manager manager, TestSession session) {
}
}
static class SuiteErrorOutputHandler extends TestRecognizerHandler {
public SuiteErrorOutputHandler() {
super("%SUITE_ERROR_OUTPUT%\\serror=(.*)"); //NOI18N
}
@Override
void updateUI( Manager manager, TestSession session) {
manager.displayOutput(session, matcher.group(1), true);
manager.displayOutput(session, "", false);
}
@Override
List<String> getRecognizedOutput() {
return Collections.<String>singletonList(matcher.group(1));
}
}
static class SuiteStartingHandler extends TestRecognizerHandler {
private boolean firstSuite = true;
public SuiteStartingHandler() {
super("%SUITE_STARTING%\\s(.+)"); //NOI18N
}
@Override
void updateUI( Manager manager, TestSession session) {
if (firstSuite) {
firstSuite = false;
manager.testStarted(session);
}
String suiteName = matcher.group(1);
session.addSuite(new TestSuite(suiteName));
manager.displaySuiteRunning(session, suiteName);
}
}
/**
* Captures the rest of %SUITE_* patterns that are not handled
* otherwise (yet).
*/
static class SuiteMiscHandler extends TestRecognizerHandler {
public SuiteMiscHandler() {
super("%SUITE_.*"); //NOI18N
}
@Override
void updateUI( Manager manager, TestSession session) {
}
}
/**
* Captures output meant for logging.
*/
static class TestLoggerHandler extends TestRecognizerHandler {
public TestLoggerHandler() {
super("%TEST_LOGGER%\\slevel=(.+)\\smsg=(.*)"); //NOI18N
}
@Override
void updateUI( Manager manager, TestSession session) {
Level level = Level.parse(matcher.group(1));
if (LOGGER.isLoggable(level))
LOGGER.log(level, matcher.group(2));
}
}
}