From 723a1d49737580cc6a9534c427467c6407c61465 Mon Sep 17 00:00:00 2001 From: Bernd Hufmann Date: Fri, 22 Jan 2016 15:43:47 -0500 Subject: [PATCH] lttng: add SWTBot tests for verifying Control flow view sorting Change-Id: I17e7803f95eca3fedbe8377b91c13a48c1a91565 Signed-off-by: Bernd Hufmann Reviewed-on: https://git.eclipse.org/r/65025 Reviewed-by: Hudson CI Reviewed-by: Matthew Khouzam Tested-by: Matthew Khouzam --- .../tests/ControlFlowViewSortingTest.java | 288 ++++++++++++++++++ .../ui/swtbot/tests/ControlFlowViewTest.java | 29 -- .../ui/swtbot/tests/KernelTestBase.java | 47 ++- 3 files changed, 330 insertions(+), 34 deletions(-) create mode 100644 lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/ControlFlowViewSortingTest.java diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/ControlFlowViewSortingTest.java b/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/ControlFlowViewSortingTest.java new file mode 100644 index 0000000000..01e5dedd8d --- /dev/null +++ b/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/ControlFlowViewSortingTest.java @@ -0,0 +1,288 @@ +/******************************************************************************* + * Copyright (c) 2016 Ericsson + * + * 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; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import java.io.IOException; + +import org.eclipse.core.runtime.FileLocator; +import org.eclipse.core.runtime.preferences.IEclipsePreferences; +import org.eclipse.core.runtime.preferences.InstanceScope; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotView; +import org.eclipse.swtbot.swt.finder.SWTBot; +import org.eclipse.swtbot.swt.finder.finders.UIThreadRunnable; +import org.eclipse.swtbot.swt.finder.junit.SWTBotJunit4ClassRunner; +import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell; +import org.eclipse.swtbot.swt.finder.widgets.SWTBotToolbarButton; +import org.eclipse.swtbot.swt.finder.widgets.SWTBotTree; +import org.eclipse.swtbot.swt.finder.widgets.SWTBotTreeColumn; +import org.eclipse.swtbot.swt.finder.widgets.SWTBotTreeItem; +import org.eclipse.tracecompass.internal.tmf.core.Activator; +import org.eclipse.tracecompass.testtraces.ctf.CtfTestTrace; +import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimePreferencesConstants; +import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestampFormat; +import org.eclipse.tracecompass.tmf.ui.swtbot.tests.shared.ConditionHelpers.SWTBotTestCondition; +import org.eclipse.tracecompass.tmf.ui.swtbot.tests.shared.SWTBotUtils; +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils; +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils.Resolution; +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils.TimeFormat; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * SWTBot tests for column sorting in the Control Flow view. + * + * @author Bernd Hufmann + */ +@SuppressWarnings("restriction") +@RunWith(SWTBotJunit4ClassRunner.class) +public class ControlFlowViewSortingTest extends KernelTestBase { + + // ------------------------------------------------------------------------ + // Constants + // ------------------------------------------------------------------------ + private static final String FILTER_ACTION = "Show View Filters"; + private static final String FILTER_DIALOG_TITLE = "Filter"; + private static final String UNCHECK_ALL = "Uncheck all"; + private static final String CHECK_SUBTREE = "Check subtree"; + private static final String OK_BUTTON = "OK"; + + private static final String PROCESS_COLUMN = "Process"; + private static final int PROCESS_COLUMN_ID = 0; + private static final String TID_COLUMN = "TID"; + private static final int TID_COLUMN_ID = 1; + private static final String PTID_COLUMN = "PTID"; + private static final String BIRTH_COLUMN = "Birth time"; + private static final int BIRTH_COLUMN_ID = 3; + private static final String TRACE_COLUMN = "Trace"; + + private static final String SYSTEMD_PROCESS_NAME = "systemd"; + private static final long SYSTEMD_BIRTHTIME = 1361214078967531336L; + private static final String SYSTEMD_TID = "1"; + + private static final String KTHREAD_PROCESS_NAME = "kthreadd"; + private static final long KTHREAD_BIRTHTIME = 1361214078967533536L; + private static final String KTHREAD_TID = "2"; + + private static final String LTTNG_CONSUMER_PROCESS_NAME = "lttng-consumerd"; + private static final long LTTNG_CONSUMER_BIRTHTIME = 1361214078963717040L; + private static final String LTTNG_CONSUMER_TID = "4034"; + + // ------------------------------------------------------------------------ + // Attributes + // ------------------------------------------------------------------------ + + private SWTBotView fViewBot; + + // ------------------------------------------------------------------------ + // Housekeeping + // ------------------------------------------------------------------------ + /** + * Before Test + */ + @Override + @Before + public void before() { + + try { + IEclipsePreferences defaultPreferences = InstanceScope.INSTANCE.getNode(Activator.PLUGIN_ID); + defaultPreferences.put(ITmfTimePreferencesConstants.TIME_ZONE, "GMT-05:00"); + TmfTimestampFormat.updateDefaultFormats(); + + String tracePath = FileLocator.toFileURL(CtfTestTrace.SYNC_DEST.getTraceURL()).getPath(); + SWTBotUtils.openTrace(TRACE_PROJECT_NAME, tracePath, KERNEL_TRACE_TYPE); + fViewBot = fBot.viewByTitle("Control Flow"); + fViewBot.show(); + fViewBot.setFocus(); + } catch (IOException e) { + fail(); + } + } + + @Override + public void after() { + IEclipsePreferences defaultPreferences = InstanceScope.INSTANCE.getNode(Activator.PLUGIN_ID); + defaultPreferences.put(ITmfTimePreferencesConstants.TIME_ZONE, "Local Time"); + TmfTimestampFormat.updateDefaultFormats(); + super.after(); + } + + // ------------------------------------------------------------------------ + // Test case(s) + // ------------------------------------------------------------------------ + /** + * UI test of sorting of processes in CFV based on column selection. To verify that the sorting + * was executed correctly, the test will use bot.waitUntil() the column content has the right + * order. + */ + @Test + public void testColumnSorting() { + // Create a known state + applyFilter(); + final SWTBotTree tree = fViewBot.bot().tree(); + SWTBotTreeItem item = SWTBotUtils.getTreeItem(fBot, tree, SYSTEMD_PROCESS_NAME); + item.select(); + + testProcessSorting(tree); + testTidSorting(tree); + testPidSorting(tree); + testBirthtimeSorting(tree); + testTraceSorting(tree); + } + + // ------------------------------------------------------------------------ + // Helpers + // ------------------------------------------------------------------------ + private void applyFilter() { + // Select only certain root nodes and their children but filter out rest + SWTBotToolbarButton filterButton = fViewBot.toolbarButton(FILTER_ACTION); + filterButton.click(); + SWTBotShell shell = fBot.shell(FILTER_DIALOG_TITLE).activate(); + + SWTBot bot = shell.bot(); + SWTBotTree treeBot = bot.tree(); + bot.button(UNCHECK_ALL).click(); + + TreeCheckedCounter treeCheckCounter = new TreeCheckedCounter(treeBot); + Integer checked = UIThreadRunnable.syncExec(treeCheckCounter); + assertEquals("default", 0, checked.intValue()); + + // select root nodes and their children + checkTreeItem(bot, treeBot, SYSTEMD_PROCESS_NAME, 54); + checkTreeItem(bot, treeBot, KTHREAD_PROCESS_NAME, 88); + checkTreeItem(bot, treeBot, LTTNG_CONSUMER_PROCESS_NAME, 89); + + bot.button(OK_BUTTON).click(); + } + + private static void checkTreeItem(SWTBot bot, SWTBotTree treeBot, String process, int nbChecked) { + SWTBotTreeItem item = SWTBotUtils.getTreeItem(bot, treeBot, process); + item.select(); + bot.button(CHECK_SUBTREE).click(); + TreeCheckedCounter treeCheckCounter = new TreeCheckedCounter(treeBot); + Integer checked = UIThreadRunnable.syncExec(treeCheckCounter); + assertEquals(process, nbChecked, checked.intValue()); + } + + private static void testProcessSorting(final SWTBotTree tree) { + SWTBotTreeColumn column = tree.header(PROCESS_COLUMN); + String[] expected = { KTHREAD_PROCESS_NAME, LTTNG_CONSUMER_PROCESS_NAME, SYSTEMD_PROCESS_NAME }; + + /* Sort direction Up */ + SWTBotTestCondition condition = getSortCondition(PROCESS_COLUMN, PROCESS_COLUMN_ID, expected, tree, false); + clickColumn(tree, column, condition); + + /* Sort direction Down */ + condition = getSortCondition(PROCESS_COLUMN, 0, expected, tree, true); + clickColumn(tree, column, condition); + } + + private static void testTidSorting(final SWTBotTree tree) { + String[] expected = { SYSTEMD_TID, KTHREAD_TID, LTTNG_CONSUMER_TID }; + SWTBotTreeColumn column = tree.header(TID_COLUMN); + /* Sort direction Up */ + SWTBotTestCondition condition = getSortCondition(TID_COLUMN, TID_COLUMN_ID, expected, tree, false); + clickColumn(tree, column, condition); + + /* Sort direction Down */ + condition = getSortCondition(TID_COLUMN, TID_COLUMN_ID, expected, tree, true); + clickColumn(tree, column, condition); + } + + /* + * Note: In this test systemd and kthreadd have PTID 0 where + * lttng-consumerd has PTID -1 that is unknown. Currently + * in CFV PTID is only shown when it's greater than 0. + */ + private static void testPidSorting(final SWTBotTree tree) { + SWTBotTreeColumn column = tree.header(PTID_COLUMN); + String[] expected = { LTTNG_CONSUMER_PROCESS_NAME, SYSTEMD_PROCESS_NAME, KTHREAD_PROCESS_NAME }; + /* Sort direction Up */ + SWTBotTestCondition condition = getSortCondition(PTID_COLUMN, PROCESS_COLUMN_ID, expected, tree, false); + clickColumn(tree, column, condition); + + /* Sort direction Down */ + String[] expected2 = { SYSTEMD_PROCESS_NAME, KTHREAD_PROCESS_NAME, LTTNG_CONSUMER_PROCESS_NAME }; + condition = getSortCondition(PTID_COLUMN, PROCESS_COLUMN_ID, expected2, tree, false); + clickColumn(tree, column, condition); + } + + private static void testBirthtimeSorting(final SWTBotTree tree) { + SWTBotTreeColumn column = tree.header(BIRTH_COLUMN); + String[] expected = { + Utils.formatTime(LTTNG_CONSUMER_BIRTHTIME, TimeFormat.CALENDAR, Resolution.NANOSEC), + Utils.formatTime(SYSTEMD_BIRTHTIME, TimeFormat.CALENDAR, Resolution.NANOSEC), + Utils.formatTime(KTHREAD_BIRTHTIME, TimeFormat.CALENDAR, Resolution.NANOSEC) }; + + /* Sort direction Up */ + SWTBotTestCondition condition = getSortCondition(BIRTH_COLUMN, BIRTH_COLUMN_ID, expected, tree, false); + clickColumn(tree, column, condition); + + /* Sort direction Down */ + condition = getSortCondition(BIRTH_COLUMN, BIRTH_COLUMN_ID, expected, tree, true); + clickColumn(tree, column, condition); + } + + /* + * Note: In this test only one trace is visualized in CFV. + * Sorting is done based on birth time (up direction). + * The implementation in CFV won't change the order when changing + * the direction. + */ + private static void testTraceSorting(final SWTBotTree tree) { + SWTBotTreeColumn column = tree.header(TRACE_COLUMN); + String[] expected = { LTTNG_CONSUMER_PROCESS_NAME, SYSTEMD_PROCESS_NAME, KTHREAD_PROCESS_NAME }; + + /* Sort direction Up */ + SWTBotTestCondition condition = getSortCondition(TRACE_COLUMN, PROCESS_COLUMN_ID, expected, tree, false); + clickColumn(tree, column, condition); + + /* Sort direction Down */ + condition = getSortCondition(TRACE_COLUMN, PROCESS_COLUMN_ID, expected, tree, false); + clickColumn(tree, column, condition); + } + + private static void clickColumn(final SWTBotTree tree, SWTBotTreeColumn processColumn, SWTBotTestCondition condition) { + processColumn.click(); + fBot.waitUntil(condition); + } + + private static SWTBotTestCondition getSortCondition(final String testCase, final int cell, final String[] expected, final SWTBotTree tree, final boolean reverse) { + return new SWTBotTestCondition() { + @Override + public boolean test() throws Exception { + SWTBotTreeItem[] items = tree.getAllItems(); + if (reverse) { + for (int i = expected.length - 1; i > 0; i--) { + if (!expected[i].equals(items[expected.length - (i + 1)].cell(cell))) { + return false; + } + } + } else { + for (int i = 0; i < expected.length; i++) { + if (!expected[i].equals(items[i].cell(cell))) { + return false; + } + } + } + return true; + } + @Override + public String getFailureMessage() { + return NLS.bind("Test Case: \'{0}\' failed!", testCase); + } + }; + } + +} diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/ControlFlowViewTest.java b/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/ControlFlowViewTest.java index f78c30b527..54799aa5bb 100644 --- a/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/ControlFlowViewTest.java +++ b/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/ControlFlowViewTest.java @@ -18,7 +18,6 @@ import static org.junit.Assert.assertTrue; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.swt.SWT; -import org.eclipse.swt.widgets.TreeItem; import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotView; import org.eclipse.swtbot.swt.finder.SWTBot; import org.eclipse.swtbot.swt.finder.finders.UIThreadRunnable; @@ -27,7 +26,6 @@ import org.eclipse.swtbot.swt.finder.keyboard.Keyboard; import org.eclipse.swtbot.swt.finder.keyboard.KeyboardFactory; import org.eclipse.swtbot.swt.finder.keyboard.Keystrokes; import org.eclipse.swtbot.swt.finder.matchers.WidgetOfType; -import org.eclipse.swtbot.swt.finder.results.Result; import org.eclipse.swtbot.swt.finder.results.VoidResult; import org.eclipse.swtbot.swt.finder.widgets.SWTBotLabel; import org.eclipse.swtbot.swt.finder.widgets.SWTBotToolbarButton; @@ -64,33 +62,6 @@ public class ControlFlowViewTest extends KernelTestBase { private static final String UNCHECK_SUBTREE = "Uncheck subtree"; private static final String UNCHECK_INACTIVE = "Uncheck Inactive"; - private static final class TreeCheckedCounter implements Result { - private final SWTBotTree fTreeBot; - - private TreeCheckedCounter(SWTBotTree treeBot) { - fTreeBot = treeBot; - } - - @Override - public Integer run() { - int checked = 0; - for (TreeItem item : fTreeBot.widget.getItems()) { - checked += getChecked(item); - } - return checked; - } - - private int getChecked(TreeItem item) { - int total = 0; - if (item.getChecked()) { - total++; - } - for (TreeItem child : item.getItems()) { - total += getChecked(child); - } - return total; - } - } private static final String FOLLOW_CPU_BACKWARD = "Follow CPU Backward"; private static final String FOLLOW_CPU_FORWARD = "Follow CPU Forward"; diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/KernelTestBase.java b/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/KernelTestBase.java index f049bce62d..1e3605f6d4 100644 --- a/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/KernelTestBase.java +++ b/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/KernelTestBase.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013, 2015 Ericsson + * Copyright (c) 2013, 2016 Ericsson * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v1.0 which @@ -21,12 +21,15 @@ import java.util.List; import org.apache.log4j.ConsoleAppender; import org.apache.log4j.Logger; import org.apache.log4j.SimpleLayout; +import org.eclipse.swt.widgets.TreeItem; import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot; import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotView; import org.eclipse.swtbot.swt.finder.finders.UIThreadRunnable; import org.eclipse.swtbot.swt.finder.junit.SWTBotJunit4ClassRunner; import org.eclipse.swtbot.swt.finder.results.BoolResult; +import org.eclipse.swtbot.swt.finder.results.Result; import org.eclipse.swtbot.swt.finder.utils.SWTBotPreferences; +import org.eclipse.swtbot.swt.finder.widgets.SWTBotTree; import org.eclipse.tracecompass.ctf.core.tests.shared.LttngKernelTraceGenerator; import org.eclipse.tracecompass.tmf.ui.swtbot.tests.shared.ConditionHelpers; import org.eclipse.tracecompass.tmf.ui.swtbot.tests.shared.SWTBotUtils; @@ -46,9 +49,12 @@ import org.junit.runner.RunWith; @RunWith(SWTBotJunit4ClassRunner.class) public abstract class KernelTestBase { - private static final String TRACE_TYPE = "org.eclipse.linuxtools.lttng2.kernel.tracetype"; - private static final String KERNEL_PERSPECTIVE_ID = "org.eclipse.linuxtools.lttng2.kernel.ui.perspective"; - private static final String TRACE_PROJECT_NAME = "test"; + /** LTTng kernel trace type */ + protected static final String KERNEL_TRACE_TYPE = "org.eclipse.linuxtools.lttng2.kernel.tracetype"; + /** LTTng kernel perspective */ + protected static final String KERNEL_PERSPECTIVE_ID = "org.eclipse.linuxtools.lttng2.kernel.ui.perspective"; + /** Default project name */ + protected static final String TRACE_PROJECT_NAME = "test"; /** The workbench bot */ protected static SWTWorkbenchBot fBot; @@ -119,7 +125,7 @@ public abstract class KernelTestBase { */ @Before public void before() { - SWTBotUtils.openTrace(TRACE_PROJECT_NAME, LttngKernelTraceGenerator.getPath(), TRACE_TYPE); + SWTBotUtils.openTrace(TRACE_PROJECT_NAME, LttngKernelTraceGenerator.getPath(), KERNEL_TRACE_TYPE); SWTBotUtils.activateEditor(fBot, LttngKernelTraceGenerator.getName()); } @@ -130,4 +136,35 @@ public abstract class KernelTestBase { public void after() { fBot.closeAllEditors(); } + + /** + * Class to check number of checked items + */ + static final class TreeCheckedCounter implements Result { + private final SWTBotTree fTreeBot; + + TreeCheckedCounter(SWTBotTree treeBot) { + fTreeBot = treeBot; + } + + @Override + public Integer run() { + int checked = 0; + for (TreeItem item : fTreeBot.widget.getItems()) { + checked += getChecked(item); + } + return checked; + } + + private int getChecked(TreeItem item) { + int total = 0; + if (item.getChecked()) { + total++; + } + for (TreeItem child : item.getItems()) { + total += getChecked(child); + } + return total; + } + } } -- 2.34.1