org.grails.ide.eclipse.test.GrailsProjectVersionFixerTest.java Source code

Java tutorial

Introduction

Here is the source code for org.grails.ide.eclipse.test.GrailsProjectVersionFixerTest.java

Source

/*******************************************************************************
 * Copyright (c) 2012 VMWare, Inc.
 * 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
 * https://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     VMWare, Inc. - initial API and implementation
 *******************************************************************************/
package org.grails.ide.eclipse.test;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Collection;

import junit.framework.AssertionFailedError;

import org.codehaus.jdt.groovy.model.GroovyNature;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.resources.WorkspaceJob;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.grails.ide.eclipse.commands.GrailsCommandUtils;
import org.grails.ide.eclipse.commands.GroovyCompilerVersionCheck;
import org.grails.ide.eclipse.commands.test.AbstractCommandTest;
import org.grails.ide.eclipse.core.GrailsCoreActivator;
import org.grails.ide.eclipse.core.internal.GrailsNature;
import org.grails.ide.eclipse.core.internal.classpath.SourceFolderJob;
import org.grails.ide.eclipse.core.model.GrailsVersion;
import org.grails.ide.eclipse.core.model.IGrailsInstall;
import org.grails.ide.eclipse.ui.internal.importfixes.GrailsProjectVersionFixer;
import org.springsource.ide.eclipse.commons.core.FileUtil;
import org.springsource.ide.eclipse.commons.core.ZipFileUtil;
import org.springsource.ide.eclipse.commons.frameworks.test.util.ACondition;
import org.springsource.ide.eclipse.commons.tests.util.StsTestUtil;

/**
 * @author Kris De Volder
 */
public class GrailsProjectVersionFixerTest extends AbstractCommandTest {

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        GrailsProjectVersionFixer.DEBUG = true;
        GrailsCommandUtils.DEBUG = true; // Want to see info about refresh
        // dependencies ops being executed.

        GroovyCompilerVersionCheck.testMode();
        // GrailsCoreActivator.getDefault().setKeepGrailsRunning(true);
        GrailsProjectVersionFixer.globalAskToConvertToGrailsProjectAnswer = true;
        StsTestUtil.setAutoBuilding(true);
        System.out.println("Waiting for autobuild...");
        StsTestUtil.waitForAutoBuild();
        System.out.println("Done autobuild");

        // Ensure the test project doesn't exist in the workspace before test
        // begins
        StsTestUtil.deleteAllProjects();
        // clearGrailsState(); //Workaround for
        // https://jira.grails.org/browse/GRAILS-7655 (ivy cache corruption)
    }

    @Override
    protected void tearDown() throws Exception {
        GrailsProjectVersionFixer.testMode(); // reset "precanned answers" for
        // other test runs.
        super.tearDown();
        GrailsProjectVersionFixer.DEBUG = false;
        GrailsCommandUtils.DEBUG = false;
    }

    // public void testImportVeryOldProjectAsLinkedProject() throws Throwable {
    // final URL zipFileURL =
    // this.getClass().getClassLoader().getResource("OldTestApp.zip");
    // final String projectName = "OldTestApp";
    //
    // importAsLinkedProject(zipFileURL, projectName);
    //
    // /////////////////////////////////////////////////////////////////////////////////////////////////
    // //Check a few things about this test project
    // checkImportedProject();
    // }

    /**
     * Tests whether our 'ensureDefaultGrailsVersion' test utility method works
     * properly.
     */
    public void testEnsureDefaultGrailsVersion() throws Throwable {
        // Yes, we swithc back and forth quite a few times. This ensures that
        // all code paths
        // through 'ensureDefaultGrailsVersion' get executed (different paths
        // when install
        // was already configured).
        ensureDefaultGrailsVersion(GrailsVersion.PREVIOUS_PREVIOUS);
        assertEquals(GrailsVersion.PREVIOUS_PREVIOUS, GrailsVersion.getDefault());

        ensureDefaultGrailsVersion(GrailsVersion.PREVIOUS);
        assertEquals(GrailsVersion.PREVIOUS, GrailsVersion.getDefault());

        ensureDefaultGrailsVersion(GrailsVersion.MOST_RECENT);
        assertEquals(GrailsVersion.MOST_RECENT, GrailsVersion.getDefault());

        ensureDefaultGrailsVersion(GrailsVersion.PREVIOUS);
        assertEquals(GrailsVersion.PREVIOUS, GrailsVersion.getDefault());

        ensureDefaultGrailsVersion(GrailsVersion.PREVIOUS_PREVIOUS);
        assertEquals(GrailsVersion.PREVIOUS_PREVIOUS, GrailsVersion.getDefault());
    }

    /**
     * @param zipFileURL
     * @param projectName
     * @throws Throwable
     */
    public void importAsLinkedProject(final URL zipFileURL, final String projectName) throws Throwable {
        WorkspaceJob atomic = new WorkspaceJob("Create linked project from zip") {
            @Override
            public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException {
                try {
                    // Create project folder from zipfile in some random place
                    // outside the workspace
                    File unzipLoc = FileUtil.createTempDirectory();
                    ZipFileUtil.unzip(zipFileURL, unzipLoc, new NullProgressMonitor());

                    IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
                    project = workspaceRoot.getProject(projectName);
                    IProjectDescription desc = ResourcesPlugin.getWorkspace()
                            .newProjectDescription(project.getName());
                    desc.setLocation(new Path(unzipLoc.toString()).append(project.getName()));
                    project.create(desc, null);
                    project.open(null);
                    // project.refreshLocal(IResource.DEPTH_INFINITE, null);

                } catch (IOException e) {
                    return new Status(IStatus.ERROR, GrailsCoreActivator.PLUGIN_ID, "bad", e);
                }
                return Status.OK_STATUS;
            }
        };
        IStatus status = atomic.run(new NullProgressMonitor());
        assertOK(status);
        assertTrue(project.isAccessible());
        assertTrue(project.getFolder("grails-app").exists());
    }

    public static void assertOK(IStatus status) throws Throwable {
        if (status.isOK())
            return;
        if (status.getException() != null)
            throw status.getException();
        throw new AssertionFailedError(status.getMessage());
    }

    public void pl() throws Throwable {
        final URL zipFileURL = this.getClass().getClassLoader().getResource("OldTestApp.zip");
        final String projectName = "OldTestApp";

        importProject(zipFileURL, projectName);

        // ///////////////////////////////////////////////////////////////////////////////////////////////
        // Check a few things about this test project
        checkImportedProject();
    }

    // /**
    // * Test for the case were a project using an older version of grails is
    // being imported, where the
    // * older version is not configured in the workspace and the user asks to
    // upgrade the project.
    // */
    // public void testImportNotSoOldProject() throws Throwable {
    // final URL zipFileURL =
    // this.getClass().getClassLoader().getResource("NotSoOldTestApp.zip");
    // final String projectName = "NotSoOldTestApp";
    //
    // importProject(zipFileURL, projectName);
    //
    // /////////////////////////////////////////////////////////////////////////////////////////////////
    // //Check a few things about this test project
    // checkImportedProject();
    // }

    /**
     * Test for the case where we import a project that doesn't have eclipse
     * specific files committed. So all configuration of Eclipse stuff has to be
     * done by our fixer.
     * <p>
     * This test is a kind of 'proxy' for importing projects from SVN/CVS, where
     * none of the Eclipse settings files have been committed.
     * <p>
     * The project being imported has a version that is the same as the default
     * Grails install of the workspace.
     */
    public void testImportBareBonesProjectWithMatchingVersion() throws Throwable {
        GrailsVersion version = GrailsVersion.MOST_RECENT;
        if (GrailsVersion.MOST_RECENT.isSnapshot()) {
            // Don't run this for snapshot builds. Too much work to create test
            // projects for moving target.
            return;
        }
        ensureDefaultGrailsVersion(version);
        final URL zipFileURL = getProjectZip("bareBonesProject", version);
        final String projectName = "testProject";

        importProject(zipFileURL, projectName);

        // This test is intended to check importing of project who's grails
        // version is the same as
        // the workspace default install...
        assertEquals(GrailsVersion.getDefault(), GrailsVersion.getGrailsVersion(project));

        // ///////////////////////////////////////////////////////////////////////////////////////////////
        // Check a few things about this test project
        checkImportedProject();
    }

    /**
     * Test for the case where we import a project that doesn't have eclipse
     * specific files committed. So all configuration of Eclipse stuff has to be
     * done by our fixer.
     * <p>
     * The project being imported has a version that is older than the default
     * Grails install of the workspace.
     */
    public void testImportBareBonesProjectWithOlderVersion() throws Throwable {
        if (GrailsVersion.MOST_RECENT.isSnapshot()) {
            // Don't run this for snapshot builds. Too much work to create test
            // projects for moving target.
            return;
        }
        if (GrailsVersion.MOST_RECENT.equals(GrailsVersion.V_2_3_0)) {
            // test failing because of bug in grails:
            // https://jira.grails.org/browse/GRAILS-10531
            return;
        }
        ensureDefaultGrailsVersion(GrailsVersion.PREVIOUS);

        final URL zipFileURL = getProjectZip("bareBonesProject", GrailsVersion.PREVIOUS);
        final String projectName = "testProject";

        importProject(zipFileURL, projectName);

        // This test is intended to check importing of project who's grails
        // version is older than
        // the workspace default install...
        assertEquals(GrailsVersion.PREVIOUS, GrailsVersion.getGrailsVersion(project));

        // ///////////////////////////////////////////////////////////////////////////////////////////////
        // Check a few things about this test project
        checkImportedProject();
    }

    /**
     * Checks a bunch of stuff about the "very old test project" once it has
     * been imported in the workspace.
     * 
     * @throws Throwable
     */
    private void checkImportedProject() throws Exception {

        // Check project config, like classpath related stuff.
        // The config may not be right initially... but should eventually become
        // correct as a background
        // refresh dependency job should get scheduled.
        // ACondition
        new ACondition("check importe project: " + project.getName()) {
            @Override
            public boolean test() throws Exception {
                System.out.println("Checking project config...");
                IJavaProject javaProject = JavaCore.create(project);

                assertDefaultOutputFolder(javaProject);
                assertTrue(project.hasNature(JavaCore.NATURE_ID)); // Should
                // have Java
                // Nature at
                // this
                // point
                assertTrue(GroovyNature.hasGroovyNature(project)); // Should
                // also have
                // Groovy
                // nature
                assertTrue(GrailsNature.isGrailsAppProject(project)); // Should
                // look
                // like
                // a
                // Grails
                // app
                // to
                // grails
                // tooling

                // /////////////////////////////////
                // Check resolved classpath stuff
                IClasspathEntry[] classPath = javaProject.getResolvedClasspath(false);

                // A whole bunch of libraries should be there, check for just a
                // few of those

                assertClassPathEntry(IClasspathEntry.CPE_LIBRARY, "/jsse.jar", classPath);
                assertClassPathEntry(IClasspathEntry.CPE_LIBRARY, "grails-core", classPath);
                assertClassPathEntry(IClasspathEntry.CPE_LIBRARY, "grails-bootstrap", classPath);
                assertClassPathEntry(IClasspathEntry.CPE_LIBRARY, "groovy-all", classPath);
                // assertClassPathEntry(IClasspathEntry.CPE_LIBRARY,
                // "servlet-api", classPath);

                // System.out.println(">>>Resolved classpath");
                // for (IClasspathEntry entry : classPath) {
                // System.out.println(kindString(entry.getEntryKind())+": "+entry.getPath());
                // }
                // System.out.println("<<<Resolved classpath");

                // /////////////////////////////////
                // Check raw classpath stuff
                classPath = javaProject.getRawClasspath();
                // for (IClasspathEntry classpathEntry : classPath) {
                // System.out.println(kindString(classpathEntry.getEntryKind())+": "+classpathEntry.getPath());
                // }

                // The usual source folders:
                assertClassPathEntry(IClasspathEntry.CPE_SOURCE, "src/java", classPath);
                assertClassPathEntry(IClasspathEntry.CPE_SOURCE, "src/groovy", classPath);
                assertClassPathEntry(IClasspathEntry.CPE_SOURCE, "grails-app/conf", classPath);
                assertClassPathEntry(IClasspathEntry.CPE_SOURCE, "grails-app/controllers", classPath);
                assertClassPathEntry(IClasspathEntry.CPE_SOURCE, "grails-app/domain", classPath);
                assertClassPathEntry(IClasspathEntry.CPE_SOURCE, "grails-app/services", classPath);
                assertClassPathEntry(IClasspathEntry.CPE_SOURCE, "grails-app/taglib", classPath);
                assertClassPathEntry(IClasspathEntry.CPE_SOURCE, "test/integration", classPath);
                assertClassPathEntry(IClasspathEntry.CPE_SOURCE, "test/unit", classPath);

                // The classpath containers for Java and Grails
                assertClassPathEntry(IClasspathEntry.CPE_CONTAINER, "org.eclipse.jdt.launching.JRE_CONTAINER",
                        classPath);
                assertClassPathEntry(IClasspathEntry.CPE_CONTAINER,
                        "org.grails.ide.eclipse.core.CLASSPATH_CONTAINER", classPath);

                // Installed plugins source folders
                assertDefaultPluginSourceFolders(project);

                System.out.println("Checking project config => OK!");
                return true;
            }

        }.waitFor(10 * 60000);
    }

    /**
     * Relates to https://issuetracker.springsource.com/browse/STS-1518. Fix for
     * this bug revamped representation of plugin source folders in STS
     * projects. This creates a need to clean up legacy linked source folders.
     * <p>
     * This assert checks whether there is anything looking like a legacy source
     * folder
     * 
     * @throws Exception
     * @throws CoreException
     */
    public void testCleanupLegacyLinkedSourceFolders() throws Exception {
        final GrailsVersion version = GrailsVersion.V_1_3_6;
        ensureDefaultGrailsVersion(version);
        final String projectName = "gTunes"; // This project was zipped before
        // we converted to the new
        // source folder layout
        final URL zipFileURL = getProjectZip(projectName, version);

        importProject(zipFileURL, projectName);

        new ACondition() {
            @Override
            public boolean test() throws Exception {
                assertNoLegacyLinkedFolders();
                return true;
            }
        }.waitFor(120000);
    }

    private void assertNoLegacyLinkedFolders() throws CoreException {
        IResource[] children = project.members(true);
        boolean seenALink = false;
        for (IResource r : children) {
            if (r.isLinked()) {
                seenALink = true;
                // The only thing we expect to see is a single link to the
                // toplevel of the grails plugins folder
                assertEquals("Legacy link not cleaned up?", SourceFolderJob.PLUGINS_FOLDER_LINK, r.getName());
            }
        }
        assertTrue("No linked resources found in project. Expected a link called: "
                + SourceFolderJob.PLUGINS_FOLDER_LINK, seenALink);
    }

    /**
     * Assert that the grails version as apparant from libs on resolved project classpath matches
     * a given version.
     */
    private void assertClasspathVersion(GrailsVersion version) throws Exception {
        IClasspathEntry[] classpath = JavaCore.create(project).getResolvedClasspath(true);
        String expectedLib = "grails-core-" + version;
        assertClassPathEntry(IClasspathEntry.CPE_LIBRARY, expectedLib, classpath);
    }

    public void testSTS1604UserChangesProjectSpecificGrailsInstall() throws Throwable {
        if (GrailsVersion.MOST_RECENT.equals(GrailsVersion.V_2_3_0)) {
            // upgrade comand from 2.2.x to 2.3 doesn't work.
            return;
        }
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>testSTS1604UserChangesProjectSpecificGrailsInstall");
        ensureDefaultGrailsVersion(GrailsVersion.MOST_RECENT);
        ensureDefaultGrailsVersion(GrailsVersion.PREVIOUS);
        final String projectName = "gTunes";
        final URL zipFileURL = getProjectZip(projectName, GrailsVersion.PREVIOUS);
        importProject(zipFileURL, projectName);

        // Double check that project was created ok with correct version numbers
        // in both eclipse settings and application.properties
        assertEquals(GrailsVersion.PREVIOUS, GrailsVersion.getEclipseGrailsVersion(project));
        assertEquals(GrailsVersion.PREVIOUS, GrailsVersion.getGrailsVersion(project));
        checkImportedProject();
        assertClasspathVersion(GrailsVersion.PREVIOUS);

        setGrailsVersion(project, GrailsVersion.MOST_RECENT);

        new ACondition() {
            @Override
            public boolean test() throws Exception {
                assertEquals("Project eclipse conf not correct", GrailsVersion.MOST_RECENT,
                        GrailsVersion.getEclipseGrailsVersion(project));
                assertEquals("Project not upgraded", GrailsVersion.MOST_RECENT,
                        GrailsVersion.getGrailsVersion(project));

                assertClasspathVersion(GrailsVersion.MOST_RECENT);
                return true;
            }

        }.waitFor(180000);

        checkImportedProject();
        System.out.println("<<<<<<<<<<<<<<<<<<<<<<<<<<testSTS1604UserChangesProjectSpecificGrailsInstall");
    }

    private void setGrailsVersion(IProject project, GrailsVersion version) throws Exception {
        version.setOn(project, false);
    }

    public void testImportProjectWithSameNameAsDeletedProject() throws Exception {
        if (GrailsVersion.MOST_RECENT.isSnapshot()) {
            // Don't run this for snapshot builds. Too much work to create test
            // projects for moving target.
            return;
        }

        // When a project is deleted, stale classpath data of this project
        // should not end up in a new project that may have the same name.
        final String projectName = "gTunes";

        // Get gTunes project with older version in workspace
        GrailsVersion version = GrailsVersion.PREVIOUS;
        ensureDefaultGrailsVersion(version);
        URL zipFileURL = getProjectZip(projectName, version);
        importProject(zipFileURL, projectName);
        assertEquals(version, GrailsVersion.getEclipseGrailsVersion(project));
        assertEquals(version, GrailsVersion.getGrailsVersion(project));
        checkImportedProject();

        project.delete(true, true, new NullProgressMonitor());

        version = GrailsVersion.MOST_RECENT;
        ensureDefaultGrailsVersion(version);
        zipFileURL = getProjectZip(projectName, version);
        importProject(zipFileURL, projectName);
        assertEquals(version, GrailsVersion.getEclipseGrailsVersion(project));
        assertEquals(version, GrailsVersion.getGrailsVersion(project));
        checkImportedProject();
    }

    public void testSTS1799ImportSpringSecurityACLSample() throws Exception {
        // Sample project from
        // https://burtbeckwith.github.com/grails-spring-security-acl/docs/manual/index.html
        // But with upgraded plugins to most recent version available now and
        // compatible with Grails 1.3.7
        final GrailsVersion version = GrailsVersion.V_1_3_7;
        // assertTrue("This test's test project needs updating to a more recent Grails version",
        // version.equals(GrailsVersion.MOST_RECENT) ||
        // version.equals(GrailsVersion.PREVIOUS));
        String projectName = "grails-contacts";

        ensureDefaultGrailsVersion(version);

        System.out.println(">>>>> Grails installs known to STS");
        Collection<IGrailsInstall> installs = GrailsCoreActivator.getDefault().getInstallManager().getAllInstalls();
        for (IGrailsInstall install : installs) {
            System.out.println("--------------------------");
            System.out.println("name          = '" + install.getName() + "'");
            System.out.println("version       = '" + install.getVersion() + "'");
            System.out.println("versionString = '" + install.getVersionString() + "'");
            System.out.println("home          = '" + install.getHome() + "'");
            System.out.println("isDefault     = '" + install.isDefault() + "'");
        }
        System.out.println("<<<<< Grails installs known to STS ====");

        URL zipFileURL = getProjectZip(projectName, version);
        importProject(zipFileURL, projectName);
        new ACondition() { // Need ACondition on build server because initially
            // will be '<unknown>' grails version
            // until version fixer has run and fixed the problem.
            @Override
            public boolean test() throws Exception {
                assertEquals(version, GrailsVersion.getEclipseGrailsVersion(project));
                return true;
            }
        }.waitFor(3000);
        assertEquals(version, GrailsVersion.getGrailsVersion(project));
        checkImportedProject();
        StsTestUtil.assertNoErrors(project);
    }

}