/*
* Copyright (C) 2015 drrb
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.drrb.rust.netbeans.cargo;
import com.github.drrb.rust.netbeans.commandrunner.CommandFuture;
import com.github.drrb.rust.netbeans.project.RustProject;
import com.github.drrb.rust.netbeans.util.Untested;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.netbeans.api.project.Project;
import org.netbeans.modules.gsf.testrunner.api.Manager;
import org.netbeans.modules.gsf.testrunner.api.Report;
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.openide.filesystems.FileObject;
@Untested(excuses = "API classes are final")
public class TestRunner {
public static class Factory {
public TestRunner create(RustProject project, Cargo cargo) {
return new TestRunner(project, cargo, Manager.getInstance());
}
}
private static final Logger LOG = Logger.getLogger(TestRunner.class.getName());
private final RustProject project;
private final Cargo cargo;
private final Manager testManager;
public TestRunner(RustProject project, Cargo cargo, Manager testManager) {
this.project = project;
this.cargo = cargo;
this.testManager = testManager;
}
//TODO: for both of these, run 'RUST_TEST_TASKS=1 cargo test --jobs 1 -- --nocapture'
// (we'll have to work out how to do that on Windows)
public void run() {
LOG.info("Running all tests");
watchCargoCommand("test");
}
public void run(FileObject file) {
LOG.log(Level.INFO, "Running tests for file {0}", file);
String moduleName = project.getCargoConfig().getModuleName(file);
watchCargoCommand("test " + moduleName + "::"); // Cargo matches this against all tests in this module
}
private void watchCargoCommand(String command) {
CommandFuture commandFuture = cargo.run(command);
commandFuture.addListener(new TestWatcher(project, testManager));
}
private static class TestWatcher extends CargoListener {
private final Map<String, SuiteInProgress> suites = new TreeMap<>();
private final Manager testManager;
private final TestSession testSession;
TestWatcher(Project project, Manager testManager) {
this.testManager = testManager;
this.testSession = new TestSession("Cargo Tests", project, TestSession.SessionType.TEST);
}
@Override
public synchronized void onStart() {
LOG.info("Starting test run");
testManager.setTestingFramework("CARGO");
testManager.testStarted(testSession);
}
@Override
protected void onTestCompleted(TestResult test) {
SuiteInProgress testSuite = getSuite(test.getModuleName());
Testcase testCase = new Testcase(test.getTestName(), null, testSession);
testCase.setStatus(test.getStatus());
testSuite.tests.add(testCase);
}
@Override
public synchronized void onFinish() {
LOG.info("Finished test run");
for (SuiteInProgress suite : suites.values()) {
testSession.addSuite(suite.suite);
testManager.displaySuiteRunning(testSession, suite.suite);
for (Testcase testCase : suite.tests) {
testSession.addTestCase(testCase);
}
Report report = testSession.getReport(0);
testManager.displayReport(testSession, report, true); // `true` means don't display "running..." next to the suite
}
testManager.sessionFinished(testSession);
}
private SuiteInProgress getSuite(String suiteName) {
if (!suites.containsKey(suiteName)) {
SuiteInProgress testSuite = new SuiteInProgress(suiteName);
suites.put(suiteName, testSuite);
}
return suites.get(suiteName);
}
private static class SuiteInProgress {
final TestSuite suite;
final List<Testcase> tests = new LinkedList<>();
SuiteInProgress(String name) {
this.suite = new TestSuite(name);
}
}
}
}