Skip to main content
aboutsummaryrefslogblamecommitdiffstats
blob: 02bb84488ebe9119d7cf1ad76cb25ba3551fbe60 (plain) (tree)
1
2
3
4
5
6
7
8
                                                                                
                                              
                                                                   
                                                                       
                                                           


                                         





                                                                                 
                                                                             
                                                                             
                                            
                                             


                                          
                    
                                
                           

                                  
                           


                         
                      
                        
                     

                                          
                     
                                 
 
                                                
                                         
                                     

                                                                   
                                 
                                       
                                            
                                      

                                       
                                         

                                          
                                          
                                         
                                                                
                                       
                                     

                                                              
                                                            
                                            
                                                                        

                                                              
                                                            
                                                      
                                                         



                                                              
                                                
                                     



                                        
                                                  

                                

                                    
                                 
                                        
                                           






                                            
                                                                                     
 
                                                                                              
 



                                                                                   
                                                  
 
                                                                                    







                                                                                   
          














                                                                                
          









                                                                                 

                                                                                                        
 


















                                                                                                
 


                                                                                                    

                                                   
                                                                                       




                                                                                                            
                 












                                                                           
                 
                            
         







                                                                                 

                                                                              
                                                
                                                       
                                           
         
 





                                                                                                     
           

























                                                                                    



                                                                                 











                                                                                    
                                                   















                                                                                            



                                                                                        
                                         







                                                          










                                                                                       
                                 
                     

                                                                                       






                                           
           
                                                                          





                                   


                                                                               

                                                
                                 

                                                                              




                                                                          
                                 



                                                       
                                 


















                                                                                       
                                 


                                                                               



                                                            
                                 



                                                       
                                 






                                                           












                                                                                  
                                 



                                                                               
                                 



                                                       
                                 






                                                           










                                                                                            
                                 





                                                                
                                 



                                                       
                                 





                                                           



                                                                       
                                 



                                                                
                                 



                                                       
                                 





                                                           




                                                                                              

                                                                                                                    



                                                            












                                                                               









                                                                                            


























                                                                                          

















                                                                                                















                                                                                        
                                                        
                                                    

                           
 

                                     
                          


                                                             


                                                                               






                                                                                 


                                                         
                 
                                                                                     

         
           







                                                                                   
                                                       




                                                               


                                                                                              





                                                                                
                                                                       

                         


                                                                                            



                                









































                                                                                              

















                                                                                   
                                                   





                                                           

                               

                                                      
           

                                                                      
                                                               

         
































                                                                                                                  
 



                                                                       




                                                                      

                                  
















                                                                                                

                                                                               
                                 
                                                             
                                                                   
                                                                                              


                                             
                                 





                                                                                          

                                                                                     
                                 






                                                                                                    
                                 





                                                                                                









                                                                                      
                                 









                                                                                         

                                                                
                                 





                                                                                               
                                                          













                                                                                                   

                                                              
                                 
                                           









                                                                                                   
                                         
                                                          




                                 
                                                    
                                                      

         
                                                     
                                                    
         




                                                     














                                                                                 
 
/*******************************************************************************
 * Copyright (c) 2010, 2014 SAP AG and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *    Mathias Kinzler (SAP AG) - initial implementation
 *******************************************************************************/
package org.eclipse.egit.ui.test;

import static org.eclipse.swtbot.eclipse.finder.waits.Conditions.waitForView;
import static org.eclipse.swtbot.swt.finder.waits.Conditions.widgetIsEnabled;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.StringTokenizer;

import org.eclipse.core.net.proxy.IProxyService;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.egit.ui.Activator;
import org.eclipse.egit.ui.internal.commit.CommitHelper;
import org.eclipse.egit.ui.internal.commit.CommitHelper.CommitInfo;
import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.jface.action.Action;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.util.StringUtils;
import org.eclipse.osgi.service.localization.BundleLocalization;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot;
import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotEditor;
import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotView;
import org.eclipse.swtbot.swt.finder.SWTBot;
import org.eclipse.swtbot.swt.finder.exceptions.WidgetNotFoundException;
import org.eclipse.swtbot.swt.finder.finders.UIThreadRunnable;
import org.eclipse.swtbot.swt.finder.results.VoidResult;
import org.eclipse.swtbot.swt.finder.waits.DefaultCondition;
import org.eclipse.swtbot.swt.finder.waits.ICondition;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotTable;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotTree;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotTreeItem;
import org.eclipse.swtbot.swt.finder.widgets.TimeoutException;
import org.eclipse.team.ui.history.IHistoryView;
import org.eclipse.ui.IViewReference;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.progress.IProgressConstants;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.util.tracker.ServiceTracker;

/**
 * Utilities to be used by SWTBot tests
 */
public class TestUtil {

	public final static String TESTAUTHOR = "Test Author <test.author@test.com>";

	public final static String TESTCOMMITTER = "Test Committer <test.committer@test.com>";

	public final static String TESTCOMMITTER_NAME = "Test Committer";

	public final static String TESTCOMMITTER_EMAIL = "test.committer@test.com";

	private final static char AMPERSAND = '&';

	private Map<Bundle, ResourceBundle> bundle2ResourceBundle = new HashMap<>();

	/**
	 * Allows access to the localized values of the EGit UI Plug-in
	 * <p>
	 * This will effectively read the plugin.properties. Ampersands (often used
	 * in menu items and field labels for keyboard shortcuts) will be filtered
	 * out (see also {@link #getPluginLocalizedValue(String, boolean)} in order
	 * to be able to reference these fields using SWTBot).
	 *
	 * @param key
	 *            the key, must not be null
	 * @return the localized value in the current default {@link Locale}, or
	 *         null
	 * @throws MissingResourceException
	 *             if no value is found for the given key
	 */
	public synchronized String getPluginLocalizedValue(String key)
			throws MissingResourceException {
		return getPluginLocalizedValue(key, false);
	}

	/**
	 * Allows access to the localized values of the EGit UI Plug-in
	 * <p>
	 *
	 * @param key
	 *            see {@link #getPluginLocalizedValue(String)}
	 * @param keepAmpersands
	 *            if <code>true</code>, ampersands will be kept
	 * @return see {@link #getPluginLocalizedValue(String)}
	 * @throws MissingResourceException
	 *             see {@link #getPluginLocalizedValue(String)}
	 */
	public synchronized String getPluginLocalizedValue(String key,
			boolean keepAmpersands) throws MissingResourceException {
		return getPluginLocalizedValue(key, keepAmpersands, Activator.getDefault().getBundle());
	}

	/**
	 * Allows access to the localized values of the given Bundle
	 * <p>
	 *
	 * @param key
	 *            see {@link #getPluginLocalizedValue(String)}
	 * @param keepAmpersands
	 *            if <code>true</code>, ampersands will be kept
	 * @param bundle
	 *            the Bundle that contains the localization
	 * @return see {@link #getPluginLocalizedValue(String)}
	 * @throws MissingResourceException
	 *             see {@link #getPluginLocalizedValue(String)}
	 */
	public synchronized String getPluginLocalizedValue(String key,
			boolean keepAmpersands, Bundle bundle) throws MissingResourceException {
		ResourceBundle myBundle = bundle2ResourceBundle.get(bundle);
		if (myBundle == null) {
			BundleContext context = bundle.getBundleContext();

			ServiceTracker<BundleLocalization, BundleLocalization> localizationTracker =
					new ServiceTracker<BundleLocalization, BundleLocalization>(
					context, BundleLocalization.class, null);
			localizationTracker.open();

			BundleLocalization location = localizationTracker.getService();
			if (location != null) {
				myBundle = location.getLocalization(bundle, Locale.getDefault().toString());
				bundle2ResourceBundle.put(bundle, myBundle);
			}

		}
		if (myBundle != null) {
			String raw = myBundle.getString(key);

			if (keepAmpersands || raw.indexOf(AMPERSAND) < 0)
				return raw;

			StringBuilder sb = new StringBuilder(raw.length());
			for (int i = 0; i < raw.length(); i++) {
				char c = raw.charAt(i);
				if (c != AMPERSAND)
					sb.append(c);
			}
			return sb.toString();
		}
		return null;
	}

	/**
	 * Utility for waiting until the execution of jobs of a given
	 * family has finished.
	 * @param family
	 * @throws InterruptedException
	 */
	public static void joinJobs(Object family) throws InterruptedException  {
		// join() returns immediately if the job is not yet scheduled.
		// To avoid unstable tests, let us first wait some time
		TestUtil.waitForJobs(100, 1000);
		Job.getJobManager().join(family, null);
		TestUtil.processUIEvents();
	}

	@SuppressWarnings("restriction")
	public static void waitForDecorations() throws InterruptedException {
		TestUtil.joinJobs(
				org.eclipse.ui.internal.decorators.DecoratorManager.FAMILY_DECORATE);
	}

	/**
	 * Utility for waiting until the execution of jobs of any family has
	 * finished or timeout is reached. If no jobs are running, the method waits
	 * given minimum wait time. While this method is waiting for jobs, UI events
	 * are processed.
	 *
	 * @param minTimeMs
	 *            minimum wait time in milliseconds
	 * @param maxTimeMs
	 *            maximum wait time in milliseconds
	 */
	public static void waitForJobs(long minTimeMs, long maxTimeMs) {
		if (maxTimeMs < minTimeMs) {
			throw new IllegalArgumentException(
					"Max time is smaller as min time!");
		}
		final long start = System.currentTimeMillis();
		while (System.currentTimeMillis() - start < minTimeMs) {
			processUIEvents();
		}
		while (!Job.getJobManager().isIdle()
				&& System.currentTimeMillis() - start < maxTimeMs) {
			processUIEvents();
		}
	}

	/**
	 * Process all queued UI events. If called from background thread, blocks
	 * until all pending events are processed in UI thread.
	 */
	public static void processUIEvents() {
		processUIEvents(0);
	}

	/**
	 * Process all queued UI events. If called from background thread, blocks
	 * until all pending events are processed in UI thread.
	 *
	 * @param timeInMillis
	 *            time to wait. During this time all UI events are processed but
	 *            the current thread is blocked
	 */
	public static void processUIEvents(final long timeInMillis) {
		if (Display.getCurrent() != null) {
			if (timeInMillis <= 0) {
				while (Display.getCurrent().readAndDispatch()) {
					// process queued ui events at least once
				}
			} else {
				long start = System.currentTimeMillis();
				while (System.currentTimeMillis() - start <= timeInMillis) {
					while (Display.getCurrent().readAndDispatch()) {
						// process queued ui events
						try {
							Thread.sleep(10);
						} catch (InterruptedException e) {
							break;
						}
					}
				}
			}
		} else {
			// synchronously refresh UI
			PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() {
				@Override
				public void run() {
					processUIEvents();
				}
			});
		}
	}

	/**
	 * Appends content to given file.
	 *
	 * @param file
	 * @param content
	 * @param append
	 *            if true, then bytes will be written to the end of the file
	 *            rather than the beginning
	 * @throws IOException
	 */
	public static void appendFileContent(File file, String content, boolean append)
			throws IOException {
		Writer fw = null;
		try {
			fw = new OutputStreamWriter(new FileOutputStream(file, append),
					"UTF-8");
			fw.append(content);
		} finally {
			if (fw != null)
				fw.close();
		}
	}

	/**
	 * Waits until the given tree has a node whose label contains text
	 * @param bot
	 * @param tree
	 * @param text
	 * @param timeout
	 * @throws TimeoutException
	 */
	public static void waitUntilTreeHasNodeContainsText(SWTBot bot,
			final SWTBotTree tree, final String text, long timeout)
			throws TimeoutException {
		bot.waitUntil(new ICondition() {

			@Override
			public boolean test() throws Exception {
				for (SWTBotTreeItem item : tree.getAllItems())
					if (item.getText().contains(text))
						return true;
				return false;
			}

			@Override
			public void init(SWTBot bot2) {
				// empty
			}

			@Override
			public String getFailureMessage() {
				return null;
			}
		}, timeout);
	}

	/**
	 * Waits until the given tree item has a node whose label contains text
	 * @param bot
	 * @param treeItem
	 * @param text
	 * @param timeout
	 * @throws TimeoutException
	 */
	public static void waitUntilTreeHasNodeContainsText(SWTBot bot,
			final SWTBotTreeItem treeItem, final String text, long timeout)
			throws TimeoutException {
		bot.waitUntil(new ICondition() {

			@Override
			public boolean test() throws Exception {
				for (SWTBotTreeItem item : treeItem.getItems())
					if (item.getText().contains(text))
						return true;
				return false;
			}

			@Override
			public void init(SWTBot bot2) {
				// empty
			}

			@Override
			public String getFailureMessage() {
				return null;
			}
		}, timeout);
	}

	/**
	 * Waits until the given tree item has a selected node with the given text
	 *
	 * @param bot
	 * @param tree
	 * @param text
	 * @param timeout
	 * @throws TimeoutException
	 */
	public static void waitUntilTreeHasSelectedNodeWithText(SWTBot bot,
			final SWTBotTree tree, final String text, long timeout)
			throws TimeoutException {
		bot.waitUntil(new ICondition() {

			@Override
			public boolean test() throws Exception {
				return tree.selection().get(0, 0).equals(text);
			}

			@Override
			public void init(SWTBot bot2) {
				// empty
			}

			@Override
			public String getFailureMessage() {
				return null;
			}
		}, timeout);
	}

	/**
	 * Waits until the given table has an item with the given text
	 * @param bot
	 * @param table
	 * @param text
	 * @param timeout
	 * @throws TimeoutException
	 */
	public static void waitUntilTableHasRowWithText(SWTBot bot, final SWTBotTable table,
			final String text, long timeout) throws TimeoutException {
		bot.waitUntil(new ICondition() {

			@Override
			public boolean test() throws Exception {
				if (table.indexOf(text)<0)
					return false;
				return true;
			}

			@Override
			public void init(SWTBot bot2) {
				// empty
			}

			@Override
			public String getFailureMessage() {
				return null;
			}
		}, timeout);
	}

	public static void waitUntilEditorIsActive(SWTWorkbenchBot bot,
			final SWTBotEditor editor, long timeout) {
		bot.waitUntil(new ICondition() {

			@Override
			public boolean test() throws Exception {
				return editor.isActive();
			}

			@Override
			public void init(SWTBot bot2) {
				// empty
			}

			@Override
			public String getFailureMessage() {
				return null;
			}
		}, timeout);
	}

	/**
	 * Disables usage of proxy servers
	 */
	public static void disableProxy() {
		BundleContext context = Activator.getDefault().getBundle().getBundleContext();
		ServiceReference<IProxyService> serviceReference = context.getServiceReference(IProxyService.class);
		IProxyService proxyService = context.getService(serviceReference);
		proxyService.setSystemProxiesEnabled(false);
		proxyService.setProxiesEnabled(false);
	}

	// TODO: this method is both needed by UI tests and Core tests
	// provide a common base for UI tests and core tests
	/**
	 * verifies that repository contains exactly the given files.
	 * @param repository
	 * @param paths
	 * @throws Exception
	 */
	public static void assertRepositoryContainsFiles(Repository repository,
			String[] paths) throws Exception {
		Set<String> expectedfiles = new HashSet<String>();
		for (String path : paths)
			expectedfiles.add(path);
		try (TreeWalk treeWalk = new TreeWalk(repository)) {
			treeWalk.addTree(repository.resolve("HEAD^{tree}"));
			treeWalk.setRecursive(true);
			while (treeWalk.next()) {
				String path = treeWalk.getPathString();
				if (!expectedfiles.contains(path))
					fail("Repository contains unexpected expected file "
							+ path);
				expectedfiles.remove(path);
			}
		}
		if (expectedfiles.size() > 0) {
			StringBuilder message = new StringBuilder(
					"Repository does not contain expected files: ");
			for (String path : expectedfiles) {
				message.append(path);
				message.append(" ");
			}
			fail(message.toString());
		}
	}

	/**
	 * verifies that repository contains exactly the given files with the given
	 * content. Usage example:<br>
	 *
	 * <code>
	 * assertRepositoryContainsFiles(repository, "foo/a.txt", "content of A",
	 *                                           "foo/b.txt", "content of B")
	 * </code>
	 * @param repository
	 * @param args
	 * @throws Exception
	 */
	public static void assertRepositoryContainsFilesWithContent(Repository repository,
			String... args) throws Exception {
		HashMap<String, String> expectedfiles = mkmap(args);
		try (TreeWalk treeWalk = new TreeWalk(repository)) {
			treeWalk.addTree(repository.resolve("HEAD^{tree}"));
			treeWalk.setRecursive(true);
			while (treeWalk.next()) {
				String path = treeWalk.getPathString();
				assertTrue(expectedfiles.containsKey(path));
				ObjectId objectId = treeWalk.getObjectId(0);
				byte[] expectedContent = expectedfiles.get(path)
						.getBytes("UTF-8");
				byte[] repoContent = treeWalk.getObjectReader().open(objectId)
						.getBytes();
				if (!Arrays.equals(repoContent, expectedContent))
					fail("File " + path + " has repository content "
							+ new String(repoContent, "UTF-8")
							+ " instead of expected content "
							+ new String(expectedContent, "UTF-8"));
				expectedfiles.remove(path);
			}
		}
		if (expectedfiles.size() > 0) {
			StringBuilder message = new StringBuilder(
					"Repository does not contain expected files: ");
			for (String path : expectedfiles.keySet()) {
				message.append(path);
				message.append(" ");
			}
			fail(message.toString());
		}
	}

	private static HashMap<String, String> mkmap(String... args) {
		if ((args.length % 2) > 0)
			throw new IllegalArgumentException("needs to be pairs");
		HashMap<String, String> map = new HashMap<String, String>();
		for (int i = 0; i < args.length; i += 2)
			map.put(args[i], args[i+1]);
		return map;
	}

	/**
	 * @param projectExplorerTree
	 * @param projects
	 *            name of a project
	 * @return the project item pertaining to the project
	 */
	public SWTBotTreeItem[] getProjectItems(SWTBotTree projectExplorerTree,
			String... projects) {
		List<SWTBotTreeItem> items = new ArrayList<SWTBotTreeItem>();
		for (SWTBotTreeItem item : projectExplorerTree.getAllItems()) {
			String itemText = item.getText();
			StringTokenizer tok = new StringTokenizer(itemText, " ");
			String name = tok.nextToken();
			// may be a dirty marker
			if (name.equals(">"))
				name = tok.nextToken();
			for (String project : projects)
				if (project.equals(name))
					items.add(item);
		}
		return items.isEmpty() ? null : items.toArray(new SWTBotTreeItem[0]);
	}

	/**
	 * Expand a node and wait until it is expanded. Use only if the node is
	 * expected to have children.
	 *
	 * @param treeItem
	 *            to expand
	 * @return the {@code treeItem}
	 */
	public static SWTBotTreeItem expandAndWait(final SWTBotTreeItem treeItem) {
		final String text = treeItem.getText();
		treeItem.expand();
		new SWTBot().waitUntil(new DefaultCondition() {

			@Override
			public boolean test() {
				if (treeItem.widget.isDisposed()) {
					return true; // Stop waiting and report failure below.
				}
				SWTBotTreeItem[] children = treeItem.getItems();
				return children != null && children.length > 0;
			}

			@Override
			public String getFailureMessage() {
				return "No children found for " + text;
			}
		});
		if (treeItem.widget.isDisposed()) {
			fail("Widget disposed while waiting for expansion of node " + text);
		}
		return treeItem;
	}

	/**
	 * Expand a node and wait until it is expanded and has a child node with the
	 * given name. Use only if the node is expected to have children.
	 *
	 * @param treeItem
	 *            to expand
	 * @param childName
	 *            to wait for
	 * @return the child node
	 */
	public static SWTBotTreeItem expandAndWaitFor(final SWTBotTreeItem treeItem,
			final String childName) {
		final String text = treeItem.getText();
		final SWTBotTreeItem[] result = { null };
		treeItem.expand();
		new SWTBot().waitUntil(new DefaultCondition() {

			@Override
			public boolean test() {
				if (treeItem.widget.isDisposed()) {
					return true; // Stop waiting and report failure below.
				}
				try {
					result[0] = treeItem.getNode(childName);
					return true;
				} catch (WidgetNotFoundException e) {
					return false;
				}
			}

			@Override
			public String getFailureMessage() {
				return "Child " + childName + " not found under " + text;
			}
		});
		if (treeItem.widget.isDisposed()) {
			fail("Widget disposed while waiting for child node " + text + '.'
					+ childName);
		}
		return result[0];
	}

	/**
	 * Navigates in the given tree to the node denoted by the labels in the
	 * path, using {@link #getNode(SWTBotTreeItem[], String)} to find children.
	 *
	 * @param tree
	 *            to navigate
	 * @param path
	 *            sequence of strings denoting the node to navigate to
	 * @return the node found
	 * @throws WidgetNotFoundException
	 *             if a node along the path cannot be found, or there are
	 *             multiple candidates
	 */
	public static SWTBotTreeItem navigateTo(SWTBotTree tree, String... path) {
		assertNotNull(path);

		new SWTBot().waitUntil(widgetIsEnabled(tree));
		SWTBotTreeItem item = getNode(tree.getAllItems(), path[0]);
		for (int i = 1; item != null && i < path.length; i++) {
			item = expandAndWait(item);
			item = getChildNode(item, path[i]);
		}
		return item;
	}

	/**
	 * @param node
	 * @param childNodeText
	 * @return child node containing childNodeText
	 * @see #getNode(SWTBotTreeItem[], String)
	 */
	public static SWTBotTreeItem getChildNode(SWTBotTreeItem node,
			String childNodeText) {
		return getNode(node.getItems(), childNodeText);
	}

	/**
	 * Finds the node that contains the given text. Throws a nice message in
	 * case the item is not found or more than one matching node was found.
	 *
	 * @param nodes
	 * @param searchText
	 * @return node containing the text
	 */
	public static SWTBotTreeItem getNode(SWTBotTreeItem[] nodes, String searchText) {
		List<String> texts = new ArrayList<String>();
		List<SWTBotTreeItem> matchingItems = new ArrayList<SWTBotTreeItem>();

		for (SWTBotTreeItem item : nodes) {
			String text = item.getText();
			if (text.contains(searchText))
				matchingItems.add(item);
			texts.add(text);
		}

		if (matchingItems.isEmpty())
			throw new WidgetNotFoundException(
					"Tree item element containg text \"" + searchText
							+ "\" was not found. Existing tree items:\n"
							+ StringUtils.join(texts, "\n"));
		else if (matchingItems.size() > 1)
			throw new WidgetNotFoundException(
					"Tree item element containg text \""
							+ searchText
							+ "\" could not be uniquely identified. All tree items:\n"
							+ StringUtils.join(texts, "\n"));

		return matchingItems.get(0);
	}

	public static RevCommit getHeadCommit(Repository repository)
			throws Exception {
		RevCommit headCommit = null;
		ObjectId parentId = repository.resolve(Constants.HEAD);
		if (parentId != null) {
			try (RevWalk rw = new RevWalk(repository)) {
				headCommit = rw.parseCommit(parentId);
			}
		}
		return headCommit;
	}

	public static void checkHeadCommit(Repository repository, String author,
			String committer, String message) throws Exception {
		CommitInfo commitInfo = CommitHelper.getHeadCommitInfo(repository);
		assertEquals(author, commitInfo.getAuthor());
		assertEquals(committer, commitInfo.getCommitter());
		assertEquals(message, commitInfo.getCommitMessage());
	}

	public static void configureTestCommitterAsUser(Repository repository) {
		StoredConfig config = repository.getConfig();
		config.setString(ConfigConstants.CONFIG_USER_SECTION, null,
				ConfigConstants.CONFIG_KEY_NAME, TestUtil.TESTCOMMITTER_NAME);
		config.setString(ConfigConstants.CONFIG_USER_SECTION, null,
				ConfigConstants.CONFIG_KEY_EMAIL, TestUtil.TESTCOMMITTER_EMAIL);
	}

	public static void waitUntilViewWithGivenIdShows(final String viewId) {
		waitForView(new BaseMatcher<IViewReference>() {
			@Override
			public boolean matches(Object item) {
				if (item instanceof IViewReference)
					return viewId.equals(((IViewReference) item).getId());
				return false;
			}

			@Override
			public void describeTo(Description description) {
				description.appendText("Wait for view with ID=" + viewId);
			}
		});
	}

	public static void waitUntilViewWithGivenTitleShows(final String viewTitle) {
		waitForView(new BaseMatcher<IViewReference>() {
			@Override
			public boolean matches(Object item) {
				if (item instanceof IViewReference)
					return viewTitle.equals(((IViewReference) item).getTitle());

				return false;
			}

			@Override
			public void describeTo(Description description) {
				description.appendText("Wait for view with title " + viewTitle);
			}
		});
	}

	public static SWTBotShell botForShellStartingWith(final String titlePrefix) {
		SWTWorkbenchBot bot = new SWTWorkbenchBot();

		Matcher<Shell> matcher = new TypeSafeMatcher<Shell>() {
			@Override
			protected boolean matchesSafely(Shell item) {
				String title = item.getText();
				return title != null && title.startsWith(titlePrefix);
			}

			@Override
			public void describeTo(Description description) {
				description.appendText("Shell with title starting with '"
						+ titlePrefix + "'");
			}
		};

		Shell shell = bot.widget(matcher);
		return new SWTBotShell(shell);
	}

	public static SWTBotView showView(final String viewId) {
		Display.getDefault().syncExec(new Runnable() {
			@Override
			public void run() {
				IWorkbenchWindow workbenchWindow = PlatformUI.getWorkbench()
						.getActiveWorkbenchWindow();
				IWorkbenchPage workbenchPage = workbenchWindow.getActivePage();
				try {
					workbenchPage.showView(viewId);
					processUIEvents();
				} catch (PartInitException e) {
					throw new RuntimeException("Showing view with ID " + viewId
							+ " failed.", e);
				}
			}
		});

		SWTWorkbenchBot bot = new SWTWorkbenchBot();
		SWTBotView viewbot = bot.viewById(viewId);
		assertNotNull("View with ID " + viewId + " not found via SWTBot.",
				viewbot);
		return viewbot;
	}

	public static void hideView(final String viewId) {
		Display.getDefault().syncExec(new Runnable() {
			@Override
			public void run() {
				IWorkbenchWindow[] windows = PlatformUI.getWorkbench()
						.getWorkbenchWindows();
				for (IWorkbenchWindow window : windows) {
					IWorkbenchPage workbenchPage = window.getActivePage();
					IViewReference[] views = workbenchPage.getViewReferences();
					for (int i = 0; i < views.length; i++) {
						IViewReference view = views[i];
						if (viewId.equals(view.getId())) {
							workbenchPage.hideView(view);
						}
					}
					processUIEvents();
				}
			}
		});
	}

	public static SWTBotView showHistoryView() {
		return showView(IHistoryView.VIEW_ID);
	}

	public static SWTBotView showExplorerView() {
		return showView(JavaUI.ID_PACKAGES);
	}

	public static SWTBotTree getExplorerTree() {
		SWTBotView view = showExplorerView();
		return view.bot().tree();
	}

	public static void openJobResultDialog(Job job) {
		assertNotNull("Job should not be null", job);
		final Action action = (Action) job
				.getProperty(IProgressConstants.ACTION_PROPERTY);
		if (action != null) {
			UIThreadRunnable.asyncExec(new VoidResult() {

				@Override
				public void run() {
					action.run();
				}
			});
		}
	}
}

Back to the top