| /****************************************************************************** |
| * Copyright (c) 2017, 2018 Ericsson |
| * |
| * 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: |
| * Patrick Tasse - Initial API and implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.tracecompass.integration.swtbot.tests.projectexplorer; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertTrue; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.util.Objects; |
| import java.util.concurrent.atomic.AtomicBoolean; |
| |
| import org.apache.commons.io.FileUtils; |
| import org.apache.log4j.ConsoleAppender; |
| import org.apache.log4j.Logger; |
| import org.apache.log4j.SimpleLayout; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IProjectDescription; |
| import org.eclipse.core.resources.IResourceChangeListener; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.NullProgressMonitor; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot; |
| import org.eclipse.swtbot.swt.finder.junit.SWTBotJunit4ClassRunner; |
| import org.eclipse.swtbot.swt.finder.utils.SWTBotPreferences; |
| import org.eclipse.swtbot.swt.finder.waits.Conditions; |
| import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell; |
| import org.eclipse.swtbot.swt.finder.widgets.SWTBotTreeItem; |
| import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager; |
| import org.eclipse.tracecompass.tmf.ui.project.model.TmfProjectRegistry; |
| import org.eclipse.tracecompass.tmf.ui.swtbot.tests.shared.ConditionHelpers; |
| import org.eclipse.tracecompass.tmf.ui.swtbot.tests.shared.SWTBotUtils; |
| import org.eclipse.tracecompass.tmf.ui.swtbot.tests.wizards.SWTBotImportWizardUtils; |
| import org.eclipse.tracecompass.tmf.ui.tests.shared.WaitUtils; |
| import org.junit.After; |
| import org.junit.AfterClass; |
| import org.junit.BeforeClass; |
| import org.junit.FixMethodOrder; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.junit.runners.MethodSorters; |
| |
| /** |
| * SWTBot test for testing Project Explorer Refresh action |
| */ |
| @FixMethodOrder(MethodSorters.NAME_ASCENDING) |
| @RunWith(SWTBotJunit4ClassRunner.class) |
| public class ProjectExplorerRefreshTest { |
| private static final String TRACE_PROJECT_NAME = "test"; |
| private static final String C_PROJECT_NAME = "c-project"; |
| |
| /** The Log4j logger instance. */ |
| private static final Logger fLogger = Logger.getRootLogger(); |
| |
| private static final long DISK_ACCESS_TIMEOUT = 120000L; |
| |
| private static final File TEST_TRACES_PATH = new File(new Path(TmfTraceManager.getTemporaryDirPath()).append("testtraces").toOSString()); |
| |
| private static final File TEST_FILE_KERNEL = new File(getPath("import/kernel-overlap-testing")); |
| private static final File TEST_FILE_KERNEL_CLASH = new File(getPath("import/z-clashes/kernel-overlap-testing")); |
| private static final File TEST_FILE_UST = new File(getPath("import/ust-overlap-testing")); |
| |
| private static SWTWorkbenchBot fBot; |
| |
| private static File fTracesFolder = null; |
| private static File fCProjectFolder = null; |
| |
| private static String getPath(String relativePath) { |
| return new Path(TEST_TRACES_PATH.getAbsolutePath()).append(relativePath).toOSString(); |
| } |
| |
| /** |
| * Test Class setup |
| * |
| * @throws Exception |
| * on error |
| */ |
| @BeforeClass |
| public static void init() throws Exception { |
| TestDirectoryStructureUtil.generateTraceStructure(TEST_TRACES_PATH); |
| |
| SWTBotUtils.initialize(); |
| |
| /* Set up for SWTBot */ |
| SWTBotPreferences.TIMEOUT = 20000; /* 20 second timeout */ |
| SWTBotPreferences.KEYBOARD_LAYOUT = "EN_US"; |
| fLogger.removeAllAppenders(); |
| fLogger.addAppender(new ConsoleAppender(new SimpleLayout(), ConsoleAppender.SYSTEM_OUT)); |
| fBot = new SWTWorkbenchBot(); |
| |
| /* Finish waiting for eclipse to load */ |
| WaitUtils.waitForJobs(); |
| |
| SWTBotUtils.createProject(TRACE_PROJECT_NAME); |
| IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(TRACE_PROJECT_NAME); |
| fTracesFolder = new File(Objects.requireNonNull(TmfProjectRegistry.getProject(project, true).getTracesFolder()).getResource().getLocation().toOSString()); |
| |
| createCProject(C_PROJECT_NAME); |
| setTracingNature(C_PROJECT_NAME); |
| IProject cProject = ResourcesPlugin.getWorkspace().getRoot().getProject(C_PROJECT_NAME); |
| fCProjectFolder = cProject.getLocation().toFile(); |
| } |
| |
| /** |
| * Test class tear down method. |
| */ |
| @AfterClass |
| public static void tearDown() { |
| SWTBotUtils.deleteProject(TRACE_PROJECT_NAME, fBot); |
| SWTBotUtils.deleteProject(C_PROJECT_NAME, fBot); |
| fLogger.removeAllAppenders(); |
| } |
| |
| /** |
| * Test tear down method. |
| */ |
| @After |
| public void afterTest() { |
| SWTBotUtils.closeSecondaryShells(fBot); |
| } |
| |
| /** |
| * Test Refresh after adding a trace on the file system. |
| * |
| * @throws IOException if an exception occurs |
| */ |
| @Test |
| public void test16_01RefreshTraceAdded() throws IOException { |
| FileUtils.copyDirectory(TEST_FILE_KERNEL, FileUtils.getFile(fTracesFolder, TEST_FILE_KERNEL.getName())); |
| FileUtils.copyDirectory(TEST_FILE_UST, FileUtils.getFile(fTracesFolder, TEST_FILE_UST.getName())); |
| SWTBotTreeItem tracesFolder = SWTBotUtils.selectTracesFolder(fBot, TRACE_PROJECT_NAME); |
| assertEquals(0, tracesFolder.getItems().length); |
| refresh(() -> tracesFolder.contextMenu().menu("Refresh").click()); |
| SWTBotTreeItem kernelTrace = SWTBotUtils.getTraceProjectItem(fBot, tracesFolder, TEST_FILE_KERNEL.getName()); |
| kernelTrace.contextMenu().menu("Select Trace Type...", "Common Trace Format", "Linux Kernel Trace").click(); |
| SWTBotTreeItem ustTrace = SWTBotUtils.getTraceProjectItem(fBot, tracesFolder, TEST_FILE_UST.getName()); |
| ustTrace.contextMenu().menu("Select Trace Type...", "Common Trace Format", "LTTng UST Trace").click(); |
| } |
| |
| /** |
| * Test Refresh after modifying trace content while trace is opened. |
| * |
| * @throws IOException if an exception occurs |
| */ |
| @Test |
| public void test16_02RefreshOpenedTraceContentModified() throws IOException { |
| SWTBotTreeItem tracesFolder = SWTBotUtils.selectTracesFolder(fBot, TRACE_PROJECT_NAME); |
| SWTBotTreeItem kernelTrace = SWTBotUtils.getTraceProjectItem(fBot, tracesFolder, TEST_FILE_KERNEL.getName()); |
| kernelTrace.contextMenu().menu("Open").click(); |
| SWTBotUtils.activateEditor(fBot, TEST_FILE_KERNEL.getName()); |
| tracesFolder.contextMenu().menu("Open As Experiment...", "Generic Experiment").click(); |
| SWTBotUtils.activateEditor(fBot, "Experiment"); |
| SWTBotTreeItem project = SWTBotUtils.selectProject(fBot, TRACE_PROJECT_NAME); |
| SWTBotTreeItem experiment = SWTBotUtils.getTraceProjectItem(fBot, project, "Experiments", "Experiment"); |
| FileUtils.copyDirectory(TEST_FILE_KERNEL_CLASH, FileUtils.getFile(fTracesFolder, TEST_FILE_KERNEL.getName()), false); |
| // false -> last modified times are copied file time stamps |
| assertTrue(kernelTrace.contextMenu().menuItems().contains("Delete Supplementary Files...")); |
| assertTrue(experiment.contextMenu().menuItems().contains("Delete Supplementary Files...")); |
| refresh(() -> tracesFolder.contextMenu().menu("Refresh").click()); |
| SWTBotShell shell = fBot.shell("Trace Changed"); |
| shell.bot().button("No").click(); |
| assertTrue(kernelTrace.contextMenu().menuItems().contains("Delete Supplementary Files...")); |
| assertTrue(experiment.contextMenu().menuItems().contains("Delete Supplementary Files...")); |
| SWTBotUtils.activateEditor(fBot, TEST_FILE_KERNEL.getName()); |
| SWTBotUtils.activateEditor(fBot, "Experiment"); |
| FileUtils.copyDirectory(TEST_FILE_KERNEL, FileUtils.getFile(fTracesFolder, TEST_FILE_KERNEL.getName()), true); |
| // true -> last modified times are original file time stamps |
| assertTrue(kernelTrace.contextMenu().menuItems().contains("Delete Supplementary Files...")); |
| refresh(() -> tracesFolder.contextMenu().menu("Refresh").click()); |
| shell = fBot.shell("Trace Changed"); |
| shell.bot().button("Yes").click(); |
| SWTBotUtils.waitUntil(treeItem -> !treeItem.contextMenu().menuItems().contains("Delete Supplementary Files..."), |
| kernelTrace, "Supplementary Files did not get deleted"); |
| assertEquals(0, fBot.editors().size()); |
| } |
| |
| /** |
| * Test Refresh after modifying trace content while trace is closed. |
| * |
| * @throws IOException if an exception occurs |
| */ |
| @Test |
| public void test16_03RefreshClosedTraceContentModified() throws IOException { |
| SWTBotTreeItem tracesFolder = SWTBotUtils.selectTracesFolder(fBot, TRACE_PROJECT_NAME); |
| SWTBotTreeItem kernelTrace = SWTBotUtils.getTraceProjectItem(fBot, tracesFolder, TEST_FILE_KERNEL.getName()); |
| SWTBotTreeItem ustTrace = SWTBotUtils.getTraceProjectItem(fBot, tracesFolder, TEST_FILE_UST.getName()); |
| kernelTrace.contextMenu().menu("Select Trace Type...", "Common Trace Format", "Linux Kernel Trace").click(); |
| kernelTrace.contextMenu().menu("Open").click(); |
| SWTBotUtils.activateEditor(fBot, TEST_FILE_KERNEL.getName()).close(); |
| tracesFolder.contextMenu().menu("Open As Experiment...", "Generic Experiment").click(); |
| SWTBotUtils.activateEditor(fBot, "Experiment").close(); |
| SWTBotTreeItem project = SWTBotUtils.selectProject(fBot, TRACE_PROJECT_NAME); |
| SWTBotTreeItem experiment = SWTBotUtils.getTraceProjectItem(fBot, project, "Experiments", "Experiment"); |
| FileUtils.touch(FileUtils.getFile(fTracesFolder, TEST_FILE_KERNEL.getName(), "channel1")); |
| FileUtils.deleteQuietly(FileUtils.getFile(fTracesFolder, TEST_FILE_UST.getName(), "channel0")); |
| assertTrue(kernelTrace.contextMenu().menuItems().contains("Delete Supplementary Files...")); |
| assertTrue(ustTrace.contextMenu().menuItems().contains("Delete Supplementary Files...")); |
| assertTrue(experiment.contextMenu().menuItems().contains("Delete Supplementary Files...")); |
| refresh(() -> tracesFolder.contextMenu().menu("Refresh").click()); |
| SWTBotUtils.waitUntil(treeItem -> !treeItem.contextMenu().menuItems().contains("Delete Supplementary Files..."), |
| kernelTrace, "Supplementary Files did not get deleted"); |
| SWTBotUtils.waitUntil(treeItem -> !treeItem.contextMenu().menuItems().contains("Delete Supplementary Files..."), |
| ustTrace, "Supplementary Files did not get deleted"); |
| SWTBotUtils.waitUntil(treeItem -> !treeItem.contextMenu().menuItems().contains("Delete Supplementary Files..."), |
| experiment, "Supplementary Files did not get deleted"); |
| } |
| |
| /** |
| * Test Refresh after deleting a trace on the file system. |
| * |
| * @throws IOException if an exception occurs |
| */ |
| @Test |
| public void test16_04RefreshTraceDeleted() throws IOException { |
| SWTBotTreeItem tracesFolder = SWTBotUtils.selectTracesFolder(fBot, TRACE_PROJECT_NAME); |
| assertEquals(2, tracesFolder.getItems().length); |
| SWTBotUtils.getTraceProjectItem(fBot, tracesFolder, TEST_FILE_KERNEL.getName()); |
| SWTBotUtils.getTraceProjectItem(fBot, tracesFolder, TEST_FILE_UST.getName()); |
| FileUtils.deleteDirectory(FileUtils.getFile(fTracesFolder, TEST_FILE_UST.getName())); |
| refresh(() -> fBot.menu().menu("File", "Refresh").click()); |
| assertEquals(1, tracesFolder.getItems().length); |
| SWTBotUtils.getTraceProjectItem(fBot, tracesFolder, TEST_FILE_KERNEL.getName()); |
| } |
| |
| /** |
| * Test refresh after deleting a trace in a c-project |
| * |
| * @throws IOException |
| * if an exception occurs |
| */ |
| @Test |
| public void test16_05CProjectRefreshTraceDeleted() throws IOException { |
| // Copy traces inside the c-project |
| FileUtils.copyDirectory(TEST_FILE_KERNEL, FileUtils.getFile(fCProjectFolder, TEST_FILE_KERNEL.getName())); |
| FileUtils.copyDirectory(TEST_FILE_UST, FileUtils.getFile(fCProjectFolder, TEST_FILE_UST.getName())); |
| SWTBotTreeItem project = SWTBotUtils.selectProject(fBot, C_PROJECT_NAME); |
| refresh(() -> project.contextMenu().menu("Refresh").click()); |
| |
| // Import traces in Trace Compass sub project as links |
| SWTBotTreeItem tracesFolder = SWTBotUtils.getTraceProjectItem(fBot, project, "Trace Compass", "Traces"); |
| tracesFolder.contextMenu().menu("Import...").click(); |
| SWTBotImportWizardUtils.selectImportFromDirectory(fBot, fCProjectFolder.getAbsolutePath()); |
| SWTBotImportWizardUtils.selectFolder(fBot, true, C_PROJECT_NAME, TEST_FILE_KERNEL.getName()); |
| SWTBotImportWizardUtils.selectFolder(fBot, true, C_PROJECT_NAME, TEST_FILE_UST.getName()); |
| SWTBotShell shell = fBot.shell("Trace Import"); |
| shell.bot().button("Finish").click(); |
| fBot.waitUntil(Conditions.shellCloses(shell), DISK_ACCESS_TIMEOUT); |
| WaitUtils.waitForJobs(); |
| |
| // Be sure that the two traces are imported |
| tracesFolder.expand(); |
| fBot.waitUntil(ConditionHelpers.treeItemCount(tracesFolder, 2)); |
| |
| // Create an experiment |
| tracesFolder.contextMenu().menu("Open As Experiment...", "Generic Experiment").click(); |
| SWTBotUtils.activateEditor(fBot, "Experiment").close(); |
| SWTBotTreeItem experiment = SWTBotUtils.getTraceProjectItem(fBot, project, "Trace Compass", "Experiments", "Experiment"); |
| experiment.expand(); |
| fBot.waitUntil(ConditionHelpers.treeItemCount(experiment, 5)); |
| |
| // Delete one trace from the c-project and verify that the trace is not in Trace Compass anymore |
| FileUtils.deleteDirectory(FileUtils.getFile(fCProjectFolder, TEST_FILE_UST.getName())); |
| refresh(() -> project.contextMenu().menu("Refresh").click()); |
| fBot.waitUntil(ConditionHelpers.treeItemCount(tracesFolder, 1)); |
| |
| // Make sure that the experiment is still there and the trace is not there |
| fBot.waitUntil(ConditionHelpers.treeItemCount(experiment, 4)); |
| |
| // Delete the remaining trace from the c-project and verify that the trace is not in Trace Compass anymore |
| FileUtils.deleteDirectory(FileUtils.getFile(fCProjectFolder, TEST_FILE_KERNEL.getName())); |
| refresh(() -> project.contextMenu().menu("Refresh").click()); |
| fBot.waitUntil(ConditionHelpers.treeItemCount(tracesFolder, 0)); |
| |
| // Experiments folder should be empty at this point |
| SWTBotTreeItem experimentsFolder = SWTBotUtils.getTraceProjectItem(fBot, project, "Trace Compass", "Experiments"); |
| experimentsFolder.expand(); |
| fBot.waitUntil(ConditionHelpers.treeItemCount(experimentsFolder, 0)); |
| } |
| |
| private static void createCProject(String projectName) throws CoreException { |
| IProgressMonitor monitor = new NullProgressMonitor(); |
| IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName); |
| project.create(monitor); |
| project.open(monitor); |
| IProjectDescription description = project.getDescription(); |
| description.setNatureIds(new String[] { "org.eclipse.cdt.core.cnature" }); |
| project.setDescription(description, monitor); |
| project.open(monitor); |
| } |
| |
| private static void setTracingNature(String projectName) { |
| SWTBotTreeItem projectItem = SWTBotUtils.selectProject(fBot, projectName); |
| projectItem.contextMenu().menu("Configure", "Configure or convert to Tracing Project").click(); |
| WaitUtils.waitForJobs(); |
| } |
| |
| private static void refresh(Runnable runnable) { |
| AtomicBoolean resourceChanged = new AtomicBoolean(); |
| IResourceChangeListener listener = event -> { |
| resourceChanged.set(true); |
| }; |
| try { |
| ResourcesPlugin.getWorkspace().addResourceChangeListener(listener); |
| SWTBotUtils.waitUntil(refresh -> { |
| refresh.run(); |
| return resourceChanged.get(); |
| }, runnable, "Resource change event not received"); |
| } finally { |
| ResourcesPlugin.getWorkspace().removeResourceChangeListener(listener); |
| } |
| } |
| } |