From 143e0680537233a90e6ffe1dfb3c2ef87e1891f1 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Genevi=C3=A8ve=20Bastien?= Date: Tue, 19 Jul 2016 10:30:30 -0400 Subject: [PATCH] linux/lttng: Add a swtbot test for UI responsiveness of kernel views MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This adds abstract swtbot classes to open a trace, then navigate it (full range, zooms, scroll, zoom back out) while some views are opened. This test is not meant to be run in the performance test suite, but enabling JUL logging with it allows to have a reproducible series of UI operations and analyze the so-obtained traces. Change-Id: Ia43c6b1244b989a6888547b43247bc9b30435dee Signed-off-by: Geneviève Bastien Reviewed-on: https://git.eclipse.org/r/78271 Reviewed-by: Matthew Khouzam Tested-by: Matthew Khouzam Reviewed-by: Hudson CI --- .../META-INF/MANIFEST.MF | 2 +- .../.classpath | 1 + .../META-INF/MANIFEST.MF | 6 +- .../tests/perf/views/UiResponseTest.java | 118 ++++++++ .../META-INF/MANIFEST.MF | 6 +- .../ui/views/controlflow/ControlFlowView.java | 2 +- .../linux/ui/views/cpuusage/CpuUsageView.java | 2 +- .../KernelMemoryUsageView.java | 2 +- .../ui/views/resources/ResourcesView.java | 2 +- .../.classpath | 1 + .../META-INF/MANIFEST.MF | 3 +- .../tests/perf/LttngUiResponseTest.java | 78 ++++++ .../.classpath | 1 + .../META-INF/MANIFEST.MF | 1 + .../tests/perf/views/ViewsResponseTest.java | 259 ++++++++++++++++++ 15 files changed, 473 insertions(+), 11 deletions(-) create mode 100644 analysis/org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests/perf/org/eclipse/tracecompass/analysis/os/linux/ui/swtbot/tests/perf/views/UiResponseTest.java create mode 100644 lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/perf/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/perf/LttngUiResponseTest.java create mode 100644 tmf/org.eclipse.tracecompass.tmf.ui.swtbot.tests/perf/org/eclipse/tracecompass/tmf/ui/swtbot/tests/perf/views/ViewsResponseTest.java diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/META-INF/MANIFEST.MF b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/META-INF/MANIFEST.MF index 577ece4e6f..3a05843db1 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/META-INF/MANIFEST.MF +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/META-INF/MANIFEST.MF @@ -22,7 +22,7 @@ Import-Package: com.google.common.base, Export-Package: org.eclipse.tracecompass.analysis.os.linux.core.contextswitch, org.eclipse.tracecompass.analysis.os.linux.core.cpuusage, org.eclipse.tracecompass.analysis.os.linux.core.event.aspect, - org.eclipse.tracecompass.analysis.os.linux.core.inputoutput;x-friends:="org.eclipse.tracecompass.analysis.os.linux.ui,org.eclipse.tracecompass.analysis.os.linux.core.tests", + org.eclipse.tracecompass.analysis.os.linux.core.inputoutput;x-friends:="org.eclipse.tracecompass.analysis.os.linux.ui,org.eclipse.tracecompass.analysis.os.linux.core.tests,org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests", org.eclipse.tracecompass.analysis.os.linux.core.kernel, org.eclipse.tracecompass.analysis.os.linux.core.kernelmemoryusage, org.eclipse.tracecompass.analysis.os.linux.core.model, diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests/.classpath b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests/.classpath index 53e1048342..aab7650a24 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests/.classpath +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests/.classpath @@ -1,6 +1,7 @@ + diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests/META-INF/MANIFEST.MF b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests/META-INF/MANIFEST.MF index 6da8c08d5e..14edf821ca 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests/META-INF/MANIFEST.MF +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests/META-INF/MANIFEST.MF @@ -7,7 +7,8 @@ Bundle-Localization: plugin Bundle-SymbolicName: org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests;singleton:=true Bundle-ActivationPolicy: lazy Bundle-RequiredExecutionEnvironment: JavaSE-1.8 -Export-Package: org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests.latency +Export-Package: org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests.latency, + org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests.perf.views Require-Bundle: org.apache.log4j, org.eclipse.core.resources, org.eclipse.core.runtime, @@ -30,5 +31,6 @@ Require-Bundle: org.apache.log4j, org.eclipse.tracecompass.analysis.os.linux.core, org.eclipse.tracecompass.segmentstore.core, org.eclipse.tracecompass.lttng2.kernel.core -Import-Package: org.eclipse.tracecompass.testtraces.ctf, +Import-Package: com.google.common.collect;version="15.0.0", + org.eclipse.tracecompass.testtraces.ctf, org.swtchart diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests/perf/org/eclipse/tracecompass/analysis/os/linux/ui/swtbot/tests/perf/views/UiResponseTest.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests/perf/org/eclipse/tracecompass/analysis/os/linux/ui/swtbot/tests/perf/views/UiResponseTest.java new file mode 100644 index 0000000000..fea9975832 --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests/perf/org/eclipse/tracecompass/analysis/os/linux/ui/swtbot/tests/perf/views/UiResponseTest.java @@ -0,0 +1,118 @@ +/******************************************************************************* + * Copyright (c) 2016 École Polytechnique de Montréal + * + * 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 + *******************************************************************************/ + +package org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests.perf.views; + +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.List; +import java.util.Map; + +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.swtbot.swt.finder.junit.SWTBotJunit4ClassRunner; +import org.eclipse.tracecompass.analysis.os.linux.core.cpuusage.KernelCpuUsageAnalysis; +import org.eclipse.tracecompass.analysis.os.linux.core.inputoutput.InputOutputAnalysisModule; +import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelAnalysisModule; +import org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.controlflow.ControlFlowView; +import org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.cpuusage.CpuUsageView; +import org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.io.diskioactivity.DiskIOActivityView; +import org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.kernelmemoryusage.KernelMemoryUsageView; +import org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.resources.ResourcesView; +import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModule; +import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; +import org.eclipse.tracecompass.tmf.ui.swtbot.tests.perf.views.ViewsResponseTest; +import org.junit.runner.RunWith; + +import com.google.common.collect.ImmutableMap; + +/** + * Test the responsiveness of Control Flow View and Resources View for different + * traces and scenarios. Ideally, when running this test, JUL logging should be + * enabled using a logger.properties file. LTTng JUL handler is advised since it + * works better with multi-threaded applications than other log handlers + * + * @author Geneviève Bastien + */ +@RunWith(SWTBotJunit4ClassRunner.class) +public abstract class UiResponseTest extends ViewsResponseTest { + + /** + * An enumeration of the views available to test + */ + protected enum OsLinuxViews { + /** + * The Control Flow View + */ + CONTROL_FLOW, + /** + * The Resources View + */ + RESOURCES, + /** + * The CPU Usage View + */ + CPU_USAGE, + /** + * The Disk IO Activity View + */ + DISK_IO_ACTIVITY, + /** + * The Kernel Memory Usage View + */ + KERNEL_MEMORY_USAGE + } + + private static final @NonNull Map VIEW_IDS = ImmutableMap.of(OsLinuxViews.CONTROL_FLOW, ControlFlowView.ID, + OsLinuxViews.RESOURCES, ResourcesView.ID, + OsLinuxViews.CPU_USAGE, CpuUsageView.ID, + OsLinuxViews.DISK_IO_ACTIVITY, DiskIOActivityView.ID, + OsLinuxViews.KERNEL_MEMORY_USAGE, KernelMemoryUsageView.ID); + + @Override + protected void beforeRunningTest(ITmfTrace trace) { + List modules = new ArrayList<>(3); + modules.add(trace.getAnalysisModule(KernelCpuUsageAnalysis.ID)); + modules.add(trace.getAnalysisModule(KernelAnalysisModule.ID)); + modules.add(trace.getAnalysisModule(InputOutputAnalysisModule.ID)); + for (IAnalysisModule module : modules) { + if (module != null) { + module.schedule(); + } + } + for (IAnalysisModule module : modules) { + if (module != null) { + assertTrue(module.waitForCompletion()); + } + } + } + + /** + * Run this swtbot with the trace specified at the specified path. The trace + * will be navigate for each view ID separately, then, after renaming the + * trace, with all the views opened. After this test, all views will be + * closed. + * + * @param tracePath + * The full path of the trace to open + * @param traceType + * The trace type of the trace to open + * @param views + * The os linux specific views to test + */ + protected void runTestWithTrace(String tracePath, String traceType, EnumSet views) { + List viewIDs = new ArrayList<>(); + for (OsLinuxViews view : views) { + viewIDs.add(VIEW_IDS.get(view)); + } + runTestWithTrace(tracePath, traceType, viewIDs); + } + +} diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/META-INF/MANIFEST.MF b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/META-INF/MANIFEST.MF index 7c4c4d6228..9b6b94a8a8 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/META-INF/MANIFEST.MF +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/META-INF/MANIFEST.MF @@ -31,9 +31,9 @@ Export-Package: org.eclipse.tracecompass.internal.analysis.os.linux.ui;x-friends org.eclipse.tracecompass.analysis.os.linux.ui.tests, org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests, org.eclipse.tracecompass.lttng2.kernel.ui", - org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.cpuusage;x-friends:="org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests", - org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.io.diskioactivity;x-internal:=true, - org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.kernelmemoryusage;x-internal:=true, + org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.cpuusage;x-friends:="org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests,org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests", + org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.io.diskioactivity;x-friends:="org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests", + org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.kernelmemoryusage;x-friends:="org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests", org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.latency;x-friends:="org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests", org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.latency.statistics;x-friends:="org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests", org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.resources; diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/controlflow/ControlFlowView.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/controlflow/ControlFlowView.java index 1b3f0f5198..22abb0fa00 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/controlflow/ControlFlowView.java +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/controlflow/ControlFlowView.java @@ -100,7 +100,7 @@ public class ControlFlowView extends AbstractStateSystemTimeGraphView { /** * View ID. */ - public static final String ID = "org.eclipse.tracecompass.analysis.os.linux.views.controlflow"; //$NON-NLS-1$ + public static final @NonNull String ID = "org.eclipse.tracecompass.analysis.os.linux.views.controlflow"; //$NON-NLS-1$ private static final String ICONS_PATH = "icons/"; //$NON-NLS-1$ private static final String OPTIMIZE_ICON = ICONS_PATH + "elcl16/Optimization.png"; //$NON-NLS-1$ diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/cpuusage/CpuUsageView.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/cpuusage/CpuUsageView.java index d1ac399c17..85202c4596 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/cpuusage/CpuUsageView.java +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/cpuusage/CpuUsageView.java @@ -51,7 +51,7 @@ import com.google.common.collect.Iterables; public class CpuUsageView extends TmfChartView { /** ID string */ - public static final String ID = "org.eclipse.tracecompass.analysis.os.linux.views.cpuusage"; //$NON-NLS-1$ + public static final @NonNull String ID = "org.eclipse.tracecompass.analysis.os.linux.views.cpuusage"; //$NON-NLS-1$ /** ID of the selected thread in the map of data in {@link TmfTraceContext} */ public static final @NonNull String CPU_USAGE_SELECTED_THREAD = ID + ".CPU_USAGE_SELECTED_TRHEAD"; //$NON-NLS-1$ diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/kernelmemoryusage/KernelMemoryUsageView.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/kernelmemoryusage/KernelMemoryUsageView.java index 0e9a83b2b1..53cea00d84 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/kernelmemoryusage/KernelMemoryUsageView.java +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/kernelmemoryusage/KernelMemoryUsageView.java @@ -36,7 +36,7 @@ import org.eclipse.tracecompass.tmf.ui.views.TmfChartView; public class KernelMemoryUsageView extends TmfChartView { /** ID string */ - public static final String ID = "org.eclipse.tracecompass.analysis.os.linux.ui.kernelmemoryusageview"; //$NON-NLS-1$ + public static final @NonNull String ID = "org.eclipse.tracecompass.analysis.os.linux.ui.kernelmemoryusageview"; //$NON-NLS-1$ /** ID of the Kernel Memory Usage view data in the data map of {@link TmfTraceContext} */ public static final @NonNull String KERNEL_MEMORY = ID + ".KERNEL_MEMORY"; //$NON-NLS-1$ diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/resources/ResourcesView.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/resources/ResourcesView.java index 7a24ddc67b..23ca9beb04 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/resources/ResourcesView.java +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/resources/ResourcesView.java @@ -58,7 +58,7 @@ import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeGraphEntry; public class ResourcesView extends AbstractStateSystemTimeGraphView { /** View ID. */ - public static final String ID = "org.eclipse.tracecompass.analysis.os.linux.views.resources"; //$NON-NLS-1$ + public static final @NonNull String ID = "org.eclipse.tracecompass.analysis.os.linux.views.resources"; //$NON-NLS-1$ /** ID of the followed CPU in the map data in {@link TmfTraceContext} */ public static final @NonNull String RESOURCES_FOLLOW_CPU = ID + ".FOLLOW_CPU"; //$NON-NLS-1$ diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/.classpath b/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/.classpath index 53e1048342..aab7650a24 100644 --- a/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/.classpath +++ b/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/.classpath @@ -1,6 +1,7 @@ + diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/META-INF/MANIFEST.MF b/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/META-INF/MANIFEST.MF index f5a183df63..52675b72e2 100644 --- a/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/META-INF/MANIFEST.MF +++ b/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/META-INF/MANIFEST.MF @@ -29,6 +29,7 @@ Require-Bundle: org.apache.log4j, org.eclipse.ui.ide, org.eclipse.ui.views, org.junit, - org.eclipse.tracecompass.analysis.graph.ui + org.eclipse.tracecompass.analysis.graph.ui, + org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests Import-Package: org.eclipse.tracecompass.testtraces.ctf, org.swtchart;version="0.7.0" diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/perf/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/perf/LttngUiResponseTest.java b/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/perf/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/perf/LttngUiResponseTest.java new file mode 100644 index 0000000000..a67341a1a2 --- /dev/null +++ b/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/perf/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/perf/LttngUiResponseTest.java @@ -0,0 +1,78 @@ +/******************************************************************************* + * Copyright (c) 2016 École Polytechnique de Montréal + * + * 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 + *******************************************************************************/ + +package org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests.perf; + +import java.io.IOException; +import java.util.EnumSet; + +import org.eclipse.core.runtime.FileLocator; +import org.eclipse.swtbot.swt.finder.junit.SWTBotJunit4ClassRunner; +import org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests.perf.views.UiResponseTest; +import org.eclipse.tracecompass.internal.lttng2.kernel.ui.views.PerspectiveFactory; +import org.eclipse.tracecompass.testtraces.ctf.CtfTestTrace; +import org.eclipse.tracecompass.tmf.ui.swtbot.tests.shared.SWTBotUtils; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Test the responsiveness of Control Flow View and Resources View for different + * traces and scenarios. Ideally, when running this test, JUL logging should be + * enabled using a logger.properties file. LTTng JUL handler is advised since it + * works better with multi-threaded applications than other log handlers + * + * @author Geneviève Bastien + */ +@RunWith(SWTBotJunit4ClassRunner.class) +public class LttngUiResponseTest extends UiResponseTest { + + private static final String TRACE_TYPE = "org.eclipse.linuxtools.lttng2.kernel.tracetype"; + + @Override + protected void prepareWorkspace() { + /* Switch to kernel perspective */ + SWTBotUtils.switchToPerspective(PerspectiveFactory.ID); + } + + /** + * Test with the django trace + * + * @throws SecurityException + * If a security manager is present and any the wrong class is + * loaded or the class loader is not the same as its ancestor's + * loader. + * @throws IllegalArgumentException + * the object is not the correct class type + * @throws IOException + * Exceptions with the trace file + */ + @Test + public void testWithDjango() throws SecurityException, IllegalArgumentException, IOException { + runTestWithTrace(FileLocator.toFileURL(CtfTestTrace.DJANGO_CLIENT.getTraceURL()).getPath(), TRACE_TYPE, EnumSet.allOf(OsLinuxViews.class)); + } + + /** + * Test with the many-threads trace + * + * @throws SecurityException + * If a security manager is present and any the wrong class is + * loaded or the class loader is not the same as its ancestor's + * loader. + * @throws IllegalArgumentException + * the object is not the correct class type + * @throws IOException + * Exceptions with the trace file + * + */ + @Test + public void testWithManyThreads() throws SecurityException, IllegalArgumentException, IOException { + runTestWithTrace(FileLocator.toFileURL(CtfTestTrace.MANY_THREADS.getTraceURL()).getPath(), TRACE_TYPE, EnumSet.of(OsLinuxViews.CONTROL_FLOW, OsLinuxViews.RESOURCES, OsLinuxViews.CPU_USAGE, OsLinuxViews.DISK_IO_ACTIVITY)); + } + +} diff --git a/tmf/org.eclipse.tracecompass.tmf.ui.swtbot.tests/.classpath b/tmf/org.eclipse.tracecompass.tmf.ui.swtbot.tests/.classpath index 20df5fc0e8..3ca0c28ec9 100644 --- a/tmf/org.eclipse.tracecompass.tmf.ui.swtbot.tests/.classpath +++ b/tmf/org.eclipse.tracecompass.tmf.ui.swtbot.tests/.classpath @@ -12,5 +12,6 @@ + diff --git a/tmf/org.eclipse.tracecompass.tmf.ui.swtbot.tests/META-INF/MANIFEST.MF b/tmf/org.eclipse.tracecompass.tmf.ui.swtbot.tests/META-INF/MANIFEST.MF index f4f683abb9..c11c36663c 100644 --- a/tmf/org.eclipse.tracecompass.tmf.ui.swtbot.tests/META-INF/MANIFEST.MF +++ b/tmf/org.eclipse.tracecompass.tmf.ui.swtbot.tests/META-INF/MANIFEST.MF @@ -35,6 +35,7 @@ Import-Package: com.google.common.collect, org.eclipse.swtbot.swt.finder.widgets, org.swtchart Export-Package: org.eclipse.tracecompass.tmf.ui.swtbot.tests.parsers.custom;x-internal:=true, + org.eclipse.tracecompass.tmf.ui.swtbot.tests.perf.views, org.eclipse.tracecompass.tmf.ui.swtbot.tests.perspectives;x-internal:=true, org.eclipse.tracecompass.tmf.ui.swtbot.tests.shared, org.eclipse.tracecompass.tmf.ui.swtbot.tests.viewers.events;x-internal:=true, diff --git a/tmf/org.eclipse.tracecompass.tmf.ui.swtbot.tests/perf/org/eclipse/tracecompass/tmf/ui/swtbot/tests/perf/views/ViewsResponseTest.java b/tmf/org.eclipse.tracecompass.tmf.ui.swtbot.tests/perf/org/eclipse/tracecompass/tmf/ui/swtbot/tests/perf/views/ViewsResponseTest.java new file mode 100644 index 0000000000..3f839491a2 --- /dev/null +++ b/tmf/org.eclipse.tracecompass.tmf.ui.swtbot.tests/perf/org/eclipse/tracecompass/tmf/ui/swtbot/tests/perf/views/ViewsResponseTest.java @@ -0,0 +1,259 @@ +/******************************************************************************* + * Copyright (c) 2016 École Polytechnique de Montréal + * + * 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 + *******************************************************************************/ + +package org.eclipse.tracecompass.tmf.ui.swtbot.tests.perf.views; + +import java.io.File; +import java.util.Collection; + +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot; +import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotView; +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.SWTBotText; +import org.eclipse.swtbot.swt.finder.widgets.SWTBotTreeItem; +import org.eclipse.tracecompass.tmf.core.signal.TmfSignalManager; +import org.eclipse.tracecompass.tmf.core.signal.TmfWindowRangeUpdatedSignal; +import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp; +import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimeRange; +import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp; +import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; +import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager; +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.views.timegraph.AbstractTimeGraphView; +import org.eclipse.ui.IWorkbenchPart; +import org.junit.After; +import org.junit.Before; +import org.junit.runner.RunWith; + +/** + * Base class to test the responsiveness of any views. The main method of this + * class, {@link #runTestWithTrace(String, String, Collection)}, will receive a + * collection of view IDs. For each view, the trace under test will be navigated + * when only the view is opened (closing all other listed views, all other + * opened views will remain opened) and also when all the views are opened + * simultaneously. In this last case, it will rename the trace so that events + * from when all the views are opened can be listed separately. + * + * @author Geneviève Bastien + */ +@RunWith(SWTBotJunit4ClassRunner.class) +public abstract class ViewsResponseTest { + + private static final String PROJECT_NAME = "test"; + + private final @NonNull SWTWorkbenchBot fBot = new SWTWorkbenchBot(); + + /** + * Specific tests will prepare the workspace for the run. For example, + * concrete classes can open perspectives, open views, prepare the layout, + * etc. + */ + protected abstract void prepareWorkspace(); + + /** + * Things to setup + */ + @Before + public void beforeClass() { + + SWTBotUtils.initialize(); + Thread.currentThread().setName("SWTBotTest"); + /* set up for swtbot */ + SWTBotPreferences.TIMEOUT = 60000; /* 60 second timeout */ + SWTBotPreferences.KEYBOARD_LAYOUT = "EN_US"; + SWTWorkbenchBot bot = new SWTWorkbenchBot(); + SWTBotUtils.closeView("welcome", bot); + /* Prepare the workspace */ + prepareWorkspace(); + /* Finish waiting for eclipse to load */ + SWTBotUtils.waitForJobs(); + + /* Create project */ + SWTBotUtils.createProject(PROJECT_NAME); + } + + /** + * Deletes the project from the workspace + */ + @After + public void cleanUp() { + /* Close editors and delete project */ + fBot.closeAllEditors(); + SWTBotUtils.deleteProject(PROJECT_NAME, fBot); + } + + private void closeAllViews(Collection viewIDs) { + viewIDs.stream().forEach(id -> { + SWTBotUtils.openView(id); + SWTBotUtils.closeViewById(id, fBot); + }); + } + + /** + * This method will be run when all views are still close, but the trace has + * been opened. For instance, if any analysis module need to have completed + * before the test, it can wait for completion here. + * + * @param trace + * The trace used for this test + */ + protected abstract void beforeRunningTest(ITmfTrace trace); + + /** + * Run this swtbot with the trace specified at the specified path. The trace + * will be navigate for each view ID separately, then, after renaming the + * trace, with all the views opened. After this test, all views will be + * closed. + * + * @param tracePath + * The full path of the trace to open + * @param traceType + * The trace type of the trace to open + * @param viewIDs + * The IDs of the views to test. + */ + protected void runTestWithTrace(String tracePath, String traceType, Collection viewIDs) { + closeAllViews(viewIDs); + /* Open the trace */ + String traceName = tracePath.substring(tracePath.lastIndexOf(File.separator, tracePath.length() - 2) + 1, tracePath.length() - 1); + SWTBotUtils.openTrace(PROJECT_NAME, tracePath, traceType); + + // Make sure all the analyses we'll need are done + ITmfTrace trace = TmfTraceManager.getInstance().getActiveTrace(); + beforeRunningTest(trace); + SWTBotUtils.waitForJobs(); + + SWTBotView view; + + for (String viewID : viewIDs) { + SWTBotUtils.openView(viewID); + view = fBot.viewById(viewID); + navigateTrace(view); + SWTBotUtils.closeViewById(viewID, fBot); + } + + // Close the trace + fBot.closeAllEditors(); + + // If there is only 1 view to test, return + if (viewIDs.size() <= 1) { + // Close the views + closeAllViews(viewIDs); + return; + } + + // Open all the views + view = null; + for (String viewID : viewIDs) { + SWTBotUtils.openView(viewID); + if (view == null) { + view = fBot.viewById(viewID); + } + } + + // Rename the trace, so the results appear under another trace and + // navigate it + renameTrace(traceName, traceName + " full"); + navigateTrace(view); + + // Close the trace + fBot.closeAllEditors(); + + // Close the views + closeAllViews(viewIDs); + } + + private void renameTrace(String oldName, String newName) { + + SWTBotTreeItem traceItem = SWTBotUtils.getTraceProjectItem(fBot, SWTBotUtils.selectTracesFolder(fBot, PROJECT_NAME), oldName); + + traceItem.contextMenu().menu("Rename...").click(); + final String RENAME_TRACE_DIALOG_TITLE = "Rename Trace"; + fBot.waitUntil(Conditions.shellIsActive(RENAME_TRACE_DIALOG_TITLE)); + SWTBotShell shell = fBot.shell(RENAME_TRACE_DIALOG_TITLE); + SWTBotText text = shell.bot().textWithLabel("New Trace name:"); + text.setText(newName); + shell.bot().button("OK").click(); + fBot.waitUntil(Conditions.shellCloses(shell)); + fBot.waitWhile(new ConditionHelpers.ActiveEventsEditor(fBot, null)); + + SWTBotTreeItem copiedItem = SWTBotUtils.getTraceProjectItem(fBot, SWTBotUtils.selectTracesFolder(fBot, PROJECT_NAME), newName); + copiedItem.contextMenu().menu("Open").click(); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + } + SWTBotUtils.waitForJobs(); + } + + // TODO: Add some vertical scrollings. With eventual 2D queries, that will + // be something to test as well + private void navigateTrace(SWTBotView view) { + TmfTimeRange originalWindowRange = TmfTraceManager.getInstance().getCurrentTraceContext().getWindowRange(); + TmfTimeRange selectionRange = TmfTraceManager.getInstance().getCurrentTraceContext().getSelectionRange(); + IWorkbenchPart part = view.getViewReference().getPart(false); + + // Set the time range to the full trace range + ITmfTrace activeTrace = TmfTraceManager.getInstance().getActiveTrace(); + TmfTimeRange fullRange = new TmfTimeRange(activeTrace.getStartTime(), activeTrace.getEndTime()); + TmfSignalManager.dispatchSignal(new TmfWindowRangeUpdatedSignal(this, fullRange)); + waitViewReady(part, selectionRange, fullRange.getEndTime()); + TmfTimeRange windowRange = fullRange; + + // Zoom in 10 times 15 percent of the range and wait for the view to be + // ready + for (int i = 0; i < 10; i++) { + double delta = (windowRange.getEndTime().getValue() - windowRange.getStartTime().getValue()) * 0.15; + TmfTimeRange newWindowRange = new TmfTimeRange(TmfTimestamp.fromNanos((long) (windowRange.getStartTime().toNanos() + delta)), TmfTimestamp.fromNanos((long) (windowRange.getEndTime().toNanos() - delta))); + TmfSignalManager.dispatchSignal(new TmfWindowRangeUpdatedSignal(this, newWindowRange)); + windowRange = newWindowRange; + waitViewReady(part, selectionRange, newWindowRange.getEndTime()); + } + + // At this zoom level, go to the end + long scrollTime = (windowRange.getEndTime().toNanos() - windowRange.getStartTime().toNanos()) / 2; + windowRange = new TmfTimeRange(TmfTimestamp.fromNanos(fullRange.getEndTime().toNanos() - (2 * scrollTime)), fullRange.getEndTime()); + TmfSignalManager.dispatchSignal(new TmfWindowRangeUpdatedSignal(this, windowRange)); + waitViewReady(part, selectionRange, windowRange.getEndTime()); + + // Scroll back horizontally half the range at a time + for (int i = 0; i < 10; i++) { + TmfTimeRange newWindowRange = new TmfTimeRange(TmfTimestamp.fromNanos(windowRange.getStartTime().toNanos() - scrollTime), TmfTimestamp.fromNanos(windowRange.getEndTime().toNanos() - scrollTime)); + TmfSignalManager.dispatchSignal(new TmfWindowRangeUpdatedSignal(this, newWindowRange)); + windowRange = newWindowRange; + waitViewReady(part, selectionRange, newWindowRange.getEndTime()); + } + + // then go all the way back to the beginning + windowRange = new TmfTimeRange(fullRange.getStartTime(), TmfTimestamp.fromNanos(fullRange.getStartTime().toNanos() + scrollTime)); + TmfSignalManager.dispatchSignal(new TmfWindowRangeUpdatedSignal(this, windowRange)); + waitViewReady(part, selectionRange, windowRange.getEndTime()); + + // and zoom out again + TmfSignalManager.dispatchSignal(new TmfWindowRangeUpdatedSignal(this, fullRange)); + waitViewReady(part, selectionRange, fullRange.getEndTime()); + + // Reset the original window range + TmfSignalManager.dispatchSignal(new TmfWindowRangeUpdatedSignal(this, originalWindowRange)); + waitViewReady(part, selectionRange, originalWindowRange.getEndTime()); + } + + private void waitViewReady(IWorkbenchPart part, @NonNull TmfTimeRange selectionRange, @NonNull ITmfTimestamp visibleTime) { + if (part instanceof AbstractTimeGraphView) { + fBot.waitUntil(ConditionHelpers.timeGraphIsReadyCondition((AbstractTimeGraphView) part, selectionRange, visibleTime)); + } + // TODO Add conditions for other kind of views + } + +} -- 2.34.1