/* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package git4idea; import com.intellij.idea.IdeaTestApplication; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.ProjectComponent; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vcs.*; import com.intellij.openapi.vcs.changes.ChangeListManager; import com.intellij.openapi.vcs.changes.ChangeListManagerImpl; import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager; import com.intellij.openapi.vcs.impl.ProjectLevelVcsManagerImpl; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.testFramework.PlatformTestCase; import com.intellij.testFramework.TestLoggerFactory; import com.intellij.testFramework.fixtures.IdeaProjectTestFixture; import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory; import com.intellij.util.ThrowableRunnable; import com.intellij.util.ui.UIUtil; import cucumber.annotation.After; import cucumber.annotation.Before; import cucumber.annotation.Order; import cucumber.runtime.ScenarioResult; import git4idea.commands.Git; import git4idea.commands.GitHttpAuthService; import git4idea.config.GitVcsSettings; import git4idea.repo.GitRepository; import git4idea.test.GitExecutor; import git4idea.test.GitHttpAuthTestService; import git4idea.test.GitTestUtil; import git4idea.test.MockVcsHelper; import org.jetbrains.annotations.NotNull; import org.junit.Assert; import org.picocontainer.MutablePicoContainer; import java.io.File; import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Collection; import java.util.Random; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicReference; import static com.intellij.openapi.vcs.Executor.cd; import static com.intellij.openapi.vcs.Executor.mkdir; /** *

The container of test environment variables which should be visible from any step definition script.

*

Most of the fields are populated in the Before hook of the {@link GeneralStepdefs}.

*/ public class GitCucumberWorld { static { Logger.setFactory(TestLoggerFactory.class); } public static String myTestRoot; public static String myProjectRoot; public static VirtualFile myProjectDir; public static Project myProject; public static GitPlatformFacade myPlatformFacade; public static Git myGit; public static GitRepository myRepository; public static GitVcsSettings mySettings; public static ChangeListManagerImpl myChangeListManager; public static GitVcs myVcs; public static MockVcsHelper myVcsHelper; public static TestVcsNotifier myNotificator; public static GitHttpAuthTestService myHttpAuthService; // only with @remote tag public static GitTestVirtualCommitsHolder virtualCommits; private static Collection myAsyncTasks; private final Logger LOG = Logger.getInstance(GitCucumberWorld.class); private IdeaProjectTestFixture myProjectFixture; private String myTestName; @Before @Order(0) public void setUp() throws Throwable { PlatformTestCase.initPlatformLangPrefix(); IdeaTestApplication.getInstance(null); myTestName = createTestName(); myProjectFixture = IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder(myTestName).getFixture(); edt(new ThrowableRunnable() { @Override public void run() throws Exception { myProjectFixture.setUp(); } }); myProject = myProjectFixture.getProject(); ((ProjectComponent)ChangeListManager.getInstance(myProject)).projectOpened(); ((ProjectComponent)VcsDirtyScopeManager.getInstance(myProject)).projectOpened(); myProjectRoot = myProject.getBasePath(); myProjectDir = myProject.getBaseDir(); myTestRoot = myProjectRoot; myPlatformFacade = ServiceManager.getService(myProject, GitPlatformFacade.class); myGit = ServiceManager.getService(myProject, Git.class); mySettings = myPlatformFacade.getSettings(myProject); mySettings.getAppSettings().setPathToGit(GitExecutor.PathHolder.GIT_EXECUTABLE); // dynamic overriding is used instead of making it in plugin.xml, // because MockVcsHelper is not ready to be a full featured implementation for all tests. myVcsHelper = overrideService(myProject, AbstractVcsHelper.class, MockVcsHelper.class); myChangeListManager = (ChangeListManagerImpl)myPlatformFacade.getChangeListManager(myProject); myNotificator = (TestVcsNotifier)ServiceManager.getService(myProject, VcsNotifier.class); myVcs = GitVcs.getInstance(myProject); virtualCommits = new GitTestVirtualCommitsHolder(); myAsyncTasks = new ArrayList(); cd(myProjectRoot); myRepository = GitTestUtil.createRepository(myProject, myProjectRoot); ProjectLevelVcsManagerImpl vcsManager = (ProjectLevelVcsManagerImpl)ProjectLevelVcsManager.getInstance(myProject); AbstractVcs vcs = vcsManager.findVcsByName("Git"); Assert.assertEquals(1, vcsManager.getRootsUnderVcs(vcs).length); GitTestUtil.assumeSupportedGitVersion(myVcs); LOG.info(getStartTestMarker()); } private String getStartTestMarker() { return "Starting " + myTestName; } // TODO should take actual feature name once we migrate to more recent cucumber lib private String createTestName() { return getClass().getName() + "-" + new Random().nextInt(); } @Before("@remote") @Order(1) public void setUpRemoteOperations() { GitTestUtil.setDefaultBuiltInServerPort(); myHttpAuthService = (GitHttpAuthTestService)ServiceManager.getService(GitHttpAuthService.class); } @Before("@nestedroot") @Order(2) public void setUpStandardMultipleRootsConfig() { cd(myProjectRoot); File community = mkdir("community"); GitTestUtil.createRepository(myProject, community.getPath()); } @After("@remote") @Order(5) public void tearDownRemoteOperations() { } @After @Order(4) public void waitForPendingTasks() throws InterruptedException, ExecutionException, TimeoutException { for (Future future : myAsyncTasks) { future.get(30, TimeUnit.SECONDS); } } @After @Order(3) public void tearDownFixture() throws Exception { edt(new ThrowableRunnable() { @Override public void run() throws Exception { myProjectFixture.tearDown(); } }); } @After @Order(2) public void cleanupDir() { FileUtil.delete(new File(myTestRoot)); } @After @Order(1) public void cleanupWorld() throws IllegalAccessException { for (Field field : GitCucumberWorld.class.getDeclaredFields()) { if (Modifier.isStatic(field.getModifiers())) { field.set(null, null); } } } @After @Order(0) public void dumpToLog(@NotNull ScenarioResult result) throws IOException { if (result.isFailed()) { TestLoggerFactory.dumpLogToStdout(getStartTestMarker()); } } public static void executeOnPooledThread(Runnable runnable) { myAsyncTasks.add(ApplicationManager.getApplication().executeOnPooledThread(runnable)); } @SuppressWarnings("unchecked") private static T overrideService(@NotNull Project project, Class serviceInterface, Class serviceImplementation) { String key = serviceInterface.getName(); MutablePicoContainer picoContainer = (MutablePicoContainer) project.getPicoContainer(); picoContainer.unregisterComponent(key); picoContainer.registerComponentImplementation(key, serviceImplementation); return (T) ServiceManager.getService(project, serviceInterface); } private static void edt(@NotNull final ThrowableRunnable runnable) throws Exception { final AtomicReference exception = new AtomicReference(); UIUtil.invokeAndWaitIfNeeded(new Runnable() { @Override public void run() { try { runnable.run(); } catch (Exception throwable) { exception.set(throwable); } } }); //noinspection ThrowableResultOfMethodCallIgnored if (exception.get() != null) { throw exception.get(); } } }