org.eclipse.ui.tests.leaks.LeakTests.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.ui.tests.leaks.LeakTests.java

Source

/*******************************************************************************
 * Copyright (c) 2004, 2009 IBM Corporation 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:
 *     IBM Corporation - initial API and implementation
 *     Remy Chi Jian Suen (Versant Corporation) - bug 255005
 *******************************************************************************/
package org.eclipse.ui.tests.leaks;

import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IPageLayout;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPartSite;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.dialogs.SaveAsDialog;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.internal.part.NullEditorInput;
import org.eclipse.ui.progress.IWorkbenchSiteProgressService;
import org.eclipse.ui.tests.api.MockViewPart;
import org.eclipse.ui.tests.harness.util.FileUtil;
import org.eclipse.ui.tests.harness.util.UITestCase;

/**
 * Very simple leak tests to determine if any of our heavy objects are not being
 * disposed properly. Note that the results of these tests will in no way
 * actually assist you in tracking down the leak.
 * 
 * @since 3.1
 */
public class LeakTests extends UITestCase {
    private IWorkbenchPage fActivePage;

    private IWorkbenchWindow fWin;

    private IProject proj;

    /**
     * @param testName
     */
    public LeakTests(String testName) {
        super(testName);
    }

    public static void checkRef(ReferenceQueue queue, Reference ref)
            throws IllegalArgumentException, InterruptedException {
        boolean flag = false;
        for (int i = 0; i < 100; i++) {
            System.runFinalization();
            System.gc();
            Thread.yield();
            processEvents();
            Reference checkRef = queue.remove(100);
            if (checkRef != null && checkRef.equals(ref)) {
                flag = true;
                break;
            }
        }

        assertTrue("Reference not enqueued", flag);
    }

    /**
     * @param queue
     * @param object
     * @return
     */
    private Reference createReference(ReferenceQueue queue, Object object) {
        return new PhantomReference(object, queue);
    }

    protected void doSetUp() throws Exception {
        super.doSetUp();
        fWin = openTestWindow(IDE.RESOURCE_PERSPECTIVE_ID);
        fActivePage = fWin.getActivePage();
    }

    protected void doTearDown() throws Exception {
        super.doTearDown();
        fWin = null;
        fActivePage = null;
        if (proj != null) {
            FileUtil.deleteProject(proj);
            proj = null;
        }
    }

    public void testSimpleEditorLeak() throws Exception {
        proj = FileUtil.createProject("testEditorLeaks");

        IFile file = FileUtil.createFile("test.mock1", proj);

        ReferenceQueue queue = new ReferenceQueue();
        IEditorPart editor = IDE.openEditor(fActivePage, file);
        assertNotNull(editor);
        Reference ref = createReference(queue, editor);
        try {
            fActivePage.closeEditor(editor, false);
            editor = null;
            checkRef(queue, ref);
        } finally {
            ref.clear();
        }
    }

    public void testSimpleViewLeak() throws Exception {
        ReferenceQueue queue = new ReferenceQueue();
        IViewPart view = fActivePage.showView(MockViewPart.ID);
        assertNotNull(view);
        Reference ref = createReference(queue, view);

        try {
            fActivePage.hideView(view);
            view = null;
            checkRef(queue, ref);
        } finally {
            ref.clear();
        }
    }

    public void testBug255005ServiceLeak() throws Exception {
        ReferenceQueue queue = new ReferenceQueue();
        IViewPart view = fActivePage.showView(MockViewPart.ID);
        assertNotNull(view);

        // create a job to schedule
        Job doNothingJob = new Job("Does Nothing") { //$NON-NLS-1$
            protected IStatus run(IProgressMonitor monitor) {
                return Status.OK_STATUS;
            }
        };

        // retrieve the progress service
        IWorkbenchSiteProgressService service = (IWorkbenchSiteProgressService) view.getSite()
                .getService(IWorkbenchSiteProgressService.class);
        // schedule it
        service.schedule(doNothingJob);

        // create a reference for our service
        Reference ref = createReference(queue, service);

        // wait for the job  to complete
        doNothingJob.join();

        try {
            // hide the view
            fActivePage.hideView(view);
            // remove our references
            service = null;
            view = null;
            // check for leaks
            checkRef(queue, ref);
        } finally {
            ref.clear();
        }
    }

    public void testBug255005SiteLeak() throws Exception {
        ReferenceQueue queue = new ReferenceQueue();
        IViewPart view = fActivePage.showView(MockViewPart.ID);
        assertNotNull(view);

        // create a job to schedule
        Job doNothingJob = new Job("Does Nothing") { //$NON-NLS-1$
            protected IStatus run(IProgressMonitor monitor) {
                return Status.OK_STATUS;
            }
        };

        // retrieve the progress service
        IWorkbenchSiteProgressService service = (IWorkbenchSiteProgressService) view.getSite()
                .getService(IWorkbenchSiteProgressService.class);
        // schedule it
        service.schedule(doNothingJob);

        IWorkbenchPartSite site = view.getSite();
        // create a reference for our site
        Reference ref = createReference(queue, site);

        // wait for the job  to complete
        doNothingJob.join();

        try {
            // hide the view
            fActivePage.hideView(view);
            // remove our references
            service = null;
            site = null;
            view = null;
            // check for leaks
            checkRef(queue, ref);
        } finally {
            ref.clear();
        }
    }

    public void testBug265449PropertiesLeak() throws Exception {
        // create a project to be selected by the 'Navigator'
        proj = FileUtil.createProject("projectToSelect");

        // show the 'Navigator'
        IViewPart navigator = fActivePage.showView(IPageLayout.ID_RES_NAV);
        // show the 'Properties' view
        IViewPart propertiesView = fActivePage.showView(IPageLayout.ID_PROP_SHEET);

        // select the project in the 'Navigator', this will cause the 'Properties'
        // view to show something, and create a PropertySheetPage, which was leaking
        navigator.getSite().getSelectionProvider().setSelection(new StructuredSelection(proj));

        // create a reference for the 'Properties' view
        ReferenceQueue queue = new ReferenceQueue();
        Reference ref = createReference(queue, propertiesView);

        try {
            // hide the views
            fActivePage.hideView(navigator);
            fActivePage.hideView(propertiesView);
            // remove our references
            navigator = null;
            propertiesView = null;
            // check for leaks
            checkRef(queue, ref);
        } finally {
            ref.clear();
        }
    }

    public void testTextEditorContextMenu() throws Exception {
        proj = FileUtil.createProject("testEditorLeaks");

        IEditorInput input = new NullEditorInput();
        ReferenceQueue queue = new ReferenceQueue();
        IEditorPart editor = IDE.openEditor(fActivePage, input, "org.eclipse.ui.tests.leak.contextEditor");
        assertTrue(editor instanceof ContextEditorPart);
        Reference ref = createReference(queue, editor);

        ContextEditorPart contextMenuEditor = (ContextEditorPart) editor;

        contextMenuEditor.showMenu();
        processEvents();

        contextMenuEditor.hideMenu();
        processEvents();

        try {
            contextMenuEditor = null;
            fActivePage.closeEditor(editor, false);
            editor = null;
            checkRef(queue, ref);
        } finally {
            ref.clear();
        }
    }

    /**
     * No idea why the following test is failing.  Doug has ran this through a 
     * profiler and for some reason the window just isn't being GCd despite 
     * there not being nay incoming references.
     */
    //    public void testSimpleWindowLeak() throws Exception {
    //        //turn off window management so that we dont have a reference to our
    //        // new
    //        //window in the listener
    //        manageWindows(false);
    //        try {
    //            ReferenceQueue queue = new ReferenceQueue();
    //            IWorkbenchWindow newWindow = openTestWindow();
    //
    //            assertNotNull(newWindow);
    //            Reference ref = createReference(queue, newWindow);
    //            try {
    //                newWindow.close();
    //                newWindow = null;
    //                checkRef(queue, ref);
    //            } finally {
    //                ref.clear();
    //            }
    //        } finally {
    //            manageWindows(true);
    //        }
    //    }

    /**
     * Test for leaks if dialog is disposed before it is closed.
     * This is really testing the framework rather than individual
     * dialogs, since many dialogs or windows will fail if the shell
     * is destroyed prior to closing them.
     * See bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=123296
     */
    public void testDestroyedDialogLeaks() throws Exception {
        ReferenceQueue queue = new ReferenceQueue();
        // Use SaveAs dialog because it's simple to invoke and utilizes
        // framework function such as storing dialog bounds.  
        // We are really testing the framework itself here.
        Dialog newDialog = new SaveAsDialog(fWin.getShell());
        newDialog.setBlockOnOpen(false);
        newDialog.open();
        assertNotNull(newDialog);
        Reference ref = createReference(queue, newDialog);
        try {
            // Dispose the window before closing it.  
            newDialog.getShell().dispose();
            newDialog.close();
            newDialog = null;
            checkRef(queue, ref);
        } finally {
            ref.clear();
        }
    }
}