/******************************************************************************* * Copyright (c) 2011, 2012 Anton Gorenkov * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Anton Gorenkov - initial API and implementation *******************************************************************************/ package org.eclipse.cdt.testsrunner.internal.model; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import org.eclipse.cdt.testsrunner.internal.launcher.TestsRunnerProviderInfo; import org.eclipse.cdt.testsrunner.internal.launcher.TestsRunnerProvidersManager; import org.eclipse.cdt.testsrunner.model.ITestingSession; import org.eclipse.core.runtime.CoreException; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.ILaunch; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.ILaunchConfigurationListener; /** * Manages all the testing sessions (creates, activates, stores history). */ public class TestingSessionsManager implements ILaunchConfigurationListener { /** Tests Runners Plug-ins Manager. */ private TestsRunnerProvidersManager testsRunnersManager; /** Testing sessions history list (the first is the newest). */ private LinkedList<TestingSession> sessions = new LinkedList<TestingSession>(); /** Currently active testing session. */ private TestingSession activeSession; /** Listeners collection. */ private List<ITestingSessionsManagerListener> listeners = new ArrayList<ITestingSessionsManagerListener>(); /** The size limit of the testing sessions history. */ private int historySizeLimit = 10; public TestingSessionsManager(TestsRunnerProvidersManager testsRunnersManager) { this.testsRunnersManager = testsRunnersManager; DebugPlugin.getDefault().getLaunchManager().addLaunchConfigurationListener(this); } /** * Tries to find the last testing session for the specified launch * configuration and Tests Runner provide plug-in. * * <p> * Usually testing frameworks do not provide the information about tests * hierarchy and total tests count before the testing is finished. So we try * to reuse them from one the previous testing sessions that meets the * requirements: * <ul> * <li>it should be for the same launch configuration; * <li>it should be completed (finished and not stopped); * <li>it should has the same tests runner; * </ul> * This function tries to find a such session. * </p> * * @param launchConfiguration required launch configuration * @param testsRunnerProviderInfo required Tests Runner provide plug-in * @return testing session or null if not found */ private TestingSession findActualPreviousSession(ILaunchConfiguration launchConfiguration, TestsRunnerProviderInfo testsRunnerProviderInfo) { String testsRunnerName = testsRunnerProviderInfo.getName(); for (TestingSession session : sessions) { // Find the latest testing session that matches the next requirements: // - it should be for the same launch configuration (should have the same parameters) // - should be already terminated (to have complete tests hierarchy structure) // - should not be stopped by user (the same as terminated) // - should have the same tests runner if (session != null) { if (launchConfiguration.equals(session.getLaunch().getLaunchConfiguration()) && session.isFinished() && !session.wasStopped() && session.getTestsRunnerProviderInfo().getName().equals(testsRunnerName)) { return session; } } } return null; } /** * Creates a new testing session for the specified launch. * * @param launch launch * @return new testing session */ public TestingSession newSession(ILaunch launch) throws CoreException { TestsRunnerProviderInfo testsRunnerProviderInfo = testsRunnersManager.getTestsRunnerProviderInfo(launch.getLaunchConfiguration()); TestingSession previousSession = findActualPreviousSession(launch.getLaunchConfiguration(), testsRunnerProviderInfo); TestingSession newTestingSession = new TestingSession(launch, testsRunnerProviderInfo, previousSession); sessions.addFirst(newTestingSession); setActiveSession(newTestingSession); truncateHistory(); return newTestingSession; } /** * Returns the testing sessions history (the first is the newest). * * @return testing sessions list */ public List<? extends ITestingSession> getSessions() { return sessions; } /** * Rewrites the testing sessions history with the specified list. Truncates * the history if necessary. * * @return testing sessions list */ public void setSessions(List<ITestingSession> newSessions) { sessions.clear(); for (ITestingSession newSession : newSessions) { sessions.add((TestingSession) newSession); } truncateHistory(); } /** * Returns the testing sessions history size. * * @return history size */ public int getSessionsCount() { return sessions.size(); } /** * Accesses the currently active testing session. * * @return testing session */ public ITestingSession getActiveSession() { return activeSession; } /** * Sets the new active testing session. * * @param newActiveSession testing session */ public void setActiveSession(ITestingSession newActiveSession) { if (activeSession != newActiveSession) { activeSession = (TestingSession) newActiveSession; // Notify listeners for (ITestingSessionsManagerListener listener : listeners) { listener.sessionActivated(activeSession); } } } /** * Adds the given listener to this registered listeners collection. * Has no effect if an identical listener is already registered. * * @param listener the listener to add */ public void addListener(ITestingSessionsManagerListener listener) { listeners.add(listener); } /** * Removes the given listener from registered listeners collection. * Has no effect if the listener is not already registered. * * @param listener the listener to remove */ public void removeListener(ITestingSessionsManagerListener listener) { listeners.remove(listener); } /** * Returns the size limit of the testing sessions history. * * @return history size limit */ public int getHistorySizeLimit() { return historySizeLimit; } /** * Sets the size limit of the testing sessions history. * * @param historySizeLimit new history size limit */ public void setHistorySizeLimit(int historySizeLimit) { this.historySizeLimit = historySizeLimit; truncateHistory(); } /** * Truncates the history list if it is longer than size limit. */ private void truncateHistory() { // The most frequently this method will be used to remove one element, so removeAll() is unnecessary here while (sessions.size() > historySizeLimit) { sessions.removeLast(); } // Handle the case when active testing session was removed from history due to truncation if (!sessions.contains(activeSession)) { ITestingSession newActiveSession = sessions.isEmpty() ? null : sessions.getFirst(); setActiveSession(newActiveSession); } } /** @since 8.1 */ @Override public void launchConfigurationAdded(ILaunchConfiguration configuration) { // Ignore } /** @since 8.1 */ @Override public void launchConfigurationChanged(ILaunchConfiguration configuration) { // Ignore } /** @since 8.1 */ @Override public void launchConfigurationRemoved(ILaunchConfiguration configuration) { for (Iterator<TestingSession> iterator = sessions.iterator(); iterator.hasNext();) { TestingSession session = iterator.next(); if (session.getLaunch().getLaunchConfiguration() .equals(configuration)) { iterator.remove(); } } truncateHistory(); } }