org.eclipse.egit.ui.test.TestUtil.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.egit.ui.test.TestUtil.java

Source

/*******************************************************************************
 * Copyright (c) 2010, 2012 SAP AG and others.
 * 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:
 *    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.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
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.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.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.osgi.service.localization.BundleLocalization;
import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot;
import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotEditor;
import org.eclipse.swtbot.swt.finder.SWTBot;
import org.eclipse.swtbot.swt.finder.waits.ICondition;
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.ui.IViewReference;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
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 ResourceBundle myBundle;

    /**
     * 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 {
        if (myBundle == null) {

            BundleContext context = Activator.getDefault().getBundle().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(Activator.getDefault().getBundle(),
                        Locale.getDefault().toString());
        }
        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 {
        Job.getJobManager().join(family, null);
    }

    /**
     * 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 {
        FileWriter fw = null;
        try {
            fw = new FileWriter(file, append);
            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() {

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

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

            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() {

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

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

            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() {

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

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

            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() {

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

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

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

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

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

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

            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);
        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);
        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();
            byte[] repoContent = treeWalk.getObjectReader().open(objectId).getBytes();
            if (!Arrays.equals(repoContent, expectedContent))
                fail("File " + path + " has repository content " + new String(repoContent)
                        + " instead of expected content " + new String(expectedContent));
            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[items.size()]);
    }

    /**
     * Retrieves a child node with the given childNodeText.
     * Nodes with dirty marker are also found (without specifying > in childNodeText)
     * @param node
     * @param childNodeText
     * @return  child node
     */
    public SWTBotTreeItem getChildNode(SWTBotTreeItem node, String childNodeText) {
        for (SWTBotTreeItem item : node.getItems()) {
            String itemText = item.getText();
            StringTokenizer tok = new StringTokenizer(itemText, " ");
            String name = tok.nextToken();
            // may be a dirty marker
            if (name.equals(">"))
                name = tok.nextToken();
            if (childNodeText.equals(name))
                return item;
        }
        return null;
    }

    public static RevCommit getHeadCommit(Repository repository) throws Exception {
        RevCommit headCommit = null;
        ObjectId parentId = repository.resolve(Constants.HEAD);
        if (parentId != null)
            headCommit = new RevWalk(repository).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>() {
            public boolean matches(Object item) {
                if (item instanceof IViewReference)
                    return viewId.equals(((IViewReference) item).getId());
                return false;
            }

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

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

                return false;
            }

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

}