/******************************************************************************* * Copyright (c) 2015 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 * * Contributors: * Marc-Andre Laperle - Initial API and implementation *******************************************************************************/ package org.eclipse.tracecompass.tmf.remote.ui.swtbot.tests.fetch; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.io.File; import java.io.IOException; import java.net.URISyntaxException; import java.util.List; import org.apache.log4j.Logger; import org.apache.log4j.varia.NullAppender; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.FileLocator; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.osgi.util.NLS; import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot; import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotView; import org.eclipse.swtbot.swt.finder.SWTBot; import org.eclipse.swtbot.swt.finder.junit.SWTBotJunit4ClassRunner; import org.eclipse.swtbot.swt.finder.keyboard.Keystrokes; import org.eclipse.swtbot.swt.finder.utils.SWTBotPreferences; import org.eclipse.swtbot.swt.finder.waits.Conditions; import org.eclipse.swtbot.swt.finder.waits.DefaultCondition; import org.eclipse.swtbot.swt.finder.widgets.SWTBotButton; import org.eclipse.swtbot.swt.finder.widgets.SWTBotCombo; import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell; import org.eclipse.swtbot.swt.finder.widgets.SWTBotText; import org.eclipse.swtbot.swt.finder.widgets.SWTBotTree; import org.eclipse.swtbot.swt.finder.widgets.SWTBotTreeItem; import org.eclipse.tracecompass.ctf.core.tests.shared.LttngTraceGenerator; import org.eclipse.tracecompass.tmf.remote.ui.swtbot.tests.TmfRemoteUISWTBotTestPlugin; import org.eclipse.tracecompass.tmf.ui.project.model.TmfProjectElement; import org.eclipse.tracecompass.tmf.ui.project.model.TmfProjectRegistry; import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceElement; import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceFolder; 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.tests.shared.WaitUtils; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; /** * Test the Fetch Remote Traces wizard. */ @RunWith(SWTBotJunit4ClassRunner.class) public class FetchRemoteTracesTest { private static final String CONNECTION_NODE_NAME = "node1"; private static final String CONNECTION_NODE_TEXT = CONNECTION_NODE_NAME + " (file://)"; private static final String LTTNG_TRACE_FILE_PATTERN = ".*synthetic.*"; private static final String FETCH_COMMAND_NAME = "Fetch Remote Traces..."; private static final String PROFILE_NAME = "new profile"; private static final String PROJECT_EXPLORER = "Project Explorer"; private static final String PROJECT_NAME = "Test"; private static final String SYSLOG_FILE_PATTERN = ".*syslog"; private static final String TRACE_GROUP_NODE_TEXT; private static final String TRACE_LOCATION; private static final String TRACE_TYPE_LTTNG = "org.eclipse.linuxtools.lttng2.kernel.tracetype"; private static final String TRACE_TYPE_SYSLOG = "org.eclipse.linuxtools.tmf.tests.stubs.trace.text.testsyslog"; private static final String WELCOME_NAME = "welcome"; private static SWTWorkbenchBot fBot; static { String traceLocation = ""; try { IPath resourcesPath = new Path("resources"); File resourcesFile = getBundleFile(resourcesPath); // Create a sub directory to test the trace folders at the same time IPath subDirFullPath = new Path(resourcesFile.getAbsolutePath()).append("generated"); File subDirFile = new File(subDirFullPath.toOSString()); subDirFile.mkdir(); IPath generatedTraceFullPath = subDirFullPath.append("synthetic-trace"); File generatedTraceFile = new File(generatedTraceFullPath.toOSString()); LttngTraceGenerator.generateLttngTrace(generatedTraceFile); traceLocation = new Path(resourcesFile.getAbsolutePath()).toString(); } catch (IOException e) { e.printStackTrace(); } catch (URISyntaxException e) { e.printStackTrace(); } TRACE_LOCATION = traceLocation; TRACE_GROUP_NODE_TEXT = TRACE_LOCATION + " (recursive)"; } private static File getBundleFile(IPath relativePath) throws URISyntaxException, IOException { return new File(FileLocator.toFileURL(FileLocator.find(TmfRemoteUISWTBotTestPlugin.getDefault().getBundle(), relativePath, null)).toURI()); } /** Test Class setup */ @BeforeClass public static void init() { SWTBotPreferences.KEYBOARD_LAYOUT = "EN_US"; SWTBotUtils.initialize(); SWTBotPreferences.TIMEOUT = 20000; /* 20 second timeout */ Logger.getRootLogger().addAppender(new NullAppender()); fBot = new SWTWorkbenchBot(); SWTBotUtils.closeView(WELCOME_NAME, fBot); SWTBotUtils.switchToTracingPerspective(); /* finish waiting for eclipse to load */ WaitUtils.waitForJobs(); } private static class TraceCountCondition extends DefaultCondition { private final TmfProjectElement fProject; private final int fExpectedCount; public TraceCountCondition(TmfProjectElement project, int expectedNumber) { fProject = project; fExpectedCount = expectedNumber; } @Override public boolean test() throws Exception { final TmfTraceFolder tracesFolder = fProject.getTracesFolder(); return ((tracesFolder != null) && (tracesFolder.getTraces().size() == fExpectedCount)); } @Override public String getFailureMessage() { return NLS.bind("The project {0} does not contain {1} traces.", fProject.getName(), fExpectedCount); } } /** * Test creating a profile, fetching all using the profile. */ @Test public void testImportAll() { testImport(new Runnable() { @Override public void run() { } }, new Runnable() { @Override public void run() { final TmfProjectElement project = TmfProjectRegistry.getProject(ResourcesPlugin.getWorkspace().getRoot().getProject(PROJECT_NAME), true); fBot.waitUntil(new TraceCountCondition(project, 2)); final TmfTraceFolder tracesFolder = project.getTracesFolder(); assertNotNull(tracesFolder); List<TmfTraceElement> traces = tracesFolder.getTraces(); assertEquals(2, traces.size()); testTrace(traces.get(0), CONNECTION_NODE_NAME + "/resources/generated/synthetic-trace", TRACE_TYPE_LTTNG); testTrace(traces.get(1), CONNECTION_NODE_NAME + "/resources/syslog", TRACE_TYPE_SYSLOG); } }); } /** * Test creating a profile, fetching only one trace */ @Test public void testImportOnlyOne() { testImport(new Runnable() { @Override public void run() { SWTBotTree tree = fBot.tree(); fBot.button("Deselect All").click(); int length = tree.getAllItems().length; assertTrue(length > 0); // Selecting the second trace under node > traceGroup SWTBotTreeItem node = getTreeItem(fBot, tree, new String[] { CONNECTION_NODE_TEXT, TRACE_GROUP_NODE_TEXT }).getNode(1); assertEquals("syslog", node.getText()); node.check(); } }, new Runnable() { @Override public void run() { TmfProjectElement project = TmfProjectRegistry.getProject(ResourcesPlugin.getWorkspace().getRoot().getProject(PROJECT_NAME), true); fBot.waitUntil(new TraceCountCondition(project, 1)); final TmfTraceFolder tracesFolder = project.getTracesFolder(); assertNotNull(tracesFolder); List<TmfTraceElement> traces = tracesFolder.getTraces(); assertEquals(1, traces.size()); testTrace(traces.get(0), CONNECTION_NODE_NAME + "/resources/syslog", TRACE_TYPE_SYSLOG); } }); } /** * Test creating a profile, fetching nothing */ @Test public void testImportNothing() { testImport(new Runnable() { @Override public void run() { fBot.button("Deselect All").click(); } }, new Runnable() { @Override public void run() { TmfProjectElement project = TmfProjectRegistry.getProject(ResourcesPlugin.getWorkspace().getRoot().getProject(PROJECT_NAME), true); final TmfTraceFolder tracesFolder = project.getTracesFolder(); assertNotNull(tracesFolder); List<TmfTraceElement> traces = tracesFolder.getTraces(); assertEquals(0, traces.size()); } }); } /** * Test to verify that empty files are omitted. */ @Test public void testEmptyFile() { testImport(new Runnable() { @Override public void run() { SWTBotTree tree = fBot.tree(); fBot.button("Deselect All").click(); int length = tree.getAllItems().length; assertTrue(length > 0); SWTBotTreeItem groupNode = getTreeItem(fBot, tree, new String[] { CONNECTION_NODE_TEXT, TRACE_GROUP_NODE_TEXT }); /* * Currently there are 3 items at the location where 1 file has 0 bytes. * Verify that empty file is not shown. */ assertEquals(2, groupNode.getItems().length); } }, new Runnable() { @Override public void run() { TmfProjectElement project = TmfProjectRegistry.getProject(ResourcesPlugin.getWorkspace().getRoot().getProject(PROJECT_NAME), true); final TmfTraceFolder tracesFolder = project.getTracesFolder(); assertNotNull(tracesFolder); List<TmfTraceElement> traces = tracesFolder.getTraces(); assertEquals(0, traces.size()); } }); } /** * Test editing a profile */ @Test public void testEditProfile() { openRemoteProfilePreferences(); createProfile(); openRemoteProfilePreferences(); // The first tree is the preference "categories" on the left side, we // need to skip it SWTBotTree tree = fBot.tree(1); final String[] traceGroupNodePath = new String[] { PROFILE_NAME, CONNECTION_NODE_TEXT, TRACE_GROUP_NODE_TEXT }; // Initial order of traces SWTBotTreeItem traceGroupNode = getTreeItem(fBot, tree, traceGroupNodePath); SWTBotTreeItem[] traceNodes = traceGroupNode.getItems(); assertEquals(2, traceNodes.length); assertEquals(LTTNG_TRACE_FILE_PATTERN, traceNodes[0].getText()); assertEquals(SYSLOG_FILE_PATTERN, traceNodes[1].getText()); // Test moving down a trace element SWTBotTreeItem traceNode = traceGroupNode.getNode(LTTNG_TRACE_FILE_PATTERN); traceNode.select(); fBot.button("Move Down").click(); traceGroupNode = getTreeItem(fBot, tree, traceGroupNodePath); traceNodes = traceGroupNode.getItems(); assertEquals(2, traceNodes.length); assertEquals(SYSLOG_FILE_PATTERN, traceNodes[0].getText()); assertEquals(LTTNG_TRACE_FILE_PATTERN, traceNodes[1].getText()); // Test moving down a trace element traceNode = traceGroupNode.getNode(LTTNG_TRACE_FILE_PATTERN); traceNode.select(); fBot.button("Move Up").click(); traceGroupNode = getTreeItem(fBot, tree, traceGroupNodePath); traceNodes = traceGroupNode.getItems(); assertEquals(2, traceNodes.length); assertEquals(LTTNG_TRACE_FILE_PATTERN, traceNodes[0].getText()); assertEquals(SYSLOG_FILE_PATTERN, traceNodes[1].getText()); // Test Copy/Paste traceNode = traceGroupNode.getNode(LTTNG_TRACE_FILE_PATTERN); traceNode.select().contextMenu("Copy").click(); traceNode.contextMenu("Paste").click(); traceNodes = traceGroupNode.getItems(); assertEquals(3, traceNodes.length); assertEquals(LTTNG_TRACE_FILE_PATTERN, traceNodes[0].getText()); assertEquals(LTTNG_TRACE_FILE_PATTERN, traceNodes[1].getText()); assertEquals(SYSLOG_FILE_PATTERN, traceNodes[2].getText()); // Test Cut/Paste traceNode = traceGroupNode.getNode(LTTNG_TRACE_FILE_PATTERN); traceNode.select().contextMenu("Cut").click(); traceNode = traceGroupNode.getNode(SYSLOG_FILE_PATTERN); traceNode.select().contextMenu("Paste").click(); traceNodes = traceGroupNode.getItems(); assertEquals(3, traceNodes.length); assertEquals(LTTNG_TRACE_FILE_PATTERN, traceNodes[0].getText()); assertEquals(SYSLOG_FILE_PATTERN, traceNodes[1].getText()); assertEquals(LTTNG_TRACE_FILE_PATTERN, traceNodes[2].getText()); // Test Delete traceNode = traceGroupNode.getNode(LTTNG_TRACE_FILE_PATTERN); traceNode.select().contextMenu("Delete").click(); traceNodes = traceGroupNode.getItems(); assertEquals(2, traceNodes.length); assertEquals(SYSLOG_FILE_PATTERN, traceNodes[0].getText()); assertEquals(LTTNG_TRACE_FILE_PATTERN, traceNodes[1].getText()); // Copy to test Paste after Delete traceNode = traceGroupNode.getNode(LTTNG_TRACE_FILE_PATTERN); traceNode.select().contextMenu("Copy").click(); traceNode = traceGroupNode.select(SYSLOG_FILE_PATTERN, LTTNG_TRACE_FILE_PATTERN); traceNode.pressShortcut(Keystrokes.DELETE); traceNodes = traceGroupNode.getItems(); assertEquals(0, traceNodes.length); // Paste after Delete traceGroupNode.contextMenu("Paste").click(); traceNodes = traceGroupNode.getItems(); assertEquals(1, traceNodes.length); assertEquals(LTTNG_TRACE_FILE_PATTERN, traceNodes[0].getText()); fBot.button("OK").click(); deleteProfile(); } private static void testImport(Runnable selectionFunctor, Runnable verifyTracesFunctor) { SWTBotUtils.createProject(PROJECT_NAME); WaitUtils.waitForJobs(); SWTBotView projectExplorerBot = fBot.viewByTitle(PROJECT_EXPLORER); assertNotNull("Cannot find " + PROJECT_EXPLORER, projectExplorerBot); projectExplorerBot.show(); SWTBotTreeItem treeItem = getTracesFolderTreeItem(projectExplorerBot); treeItem.contextMenu(FETCH_COMMAND_NAME).click(); fBot.button("Manage Profiles").click(); createProfile(); assertEquals(PROFILE_NAME, fBot.comboBoxWithLabel("Profile name:").getText()); assertEquals(CONNECTION_NODE_TEXT, fBot.textWithLabel("Nodes:").getText()); // Make sure if we go to the next page and come back that the first page // still has valid values SWTBotButton button = fBot.button("Next >"); fBot.waitUntil(Conditions.widgetIsEnabled(button)); button.click(); button = fBot.button("< Back"); fBot.waitUntil(Conditions.widgetIsEnabled(button)); button.click(); assertEquals(PROFILE_NAME, fBot.comboBoxWithLabel("Profile name:").getText()); assertEquals(CONNECTION_NODE_TEXT, fBot.textWithLabel("Nodes:").getText()); button = fBot.button("Next >"); fBot.waitUntil(Conditions.widgetIsEnabled(button)); button.click(); selectionFunctor.run(); SWTBotShell shell = fBot.activeShell(); button = fBot.button("Finish"); fBot.waitUntil(Conditions.widgetIsEnabled(button)); button.click(); fBot.waitUntil(Conditions.shellCloses(shell)); WaitUtils.waitForJobs(); verifyTracesFunctor.run(); fBot.closeAllEditors(); SWTBotUtils.deleteProject(PROJECT_NAME, fBot); deleteProfile(); } private static void createProfile() { fBot.button("Add").click(); // The first tree is the preference "categories" on the left side, we // need to skip it SWTBotTree tree = fBot.tree(1); SWTBotTreeItem treeNode = getTreeItem(fBot, tree, PROFILE_NAME, "name (ssh://userinfo@host:22)"); treeNode.select(); SWTBotText uriLabel = fBot.textWithLabel("URI:"); uriLabel.setText("file://"); SWTBotText nodeNameLabel = fBot.textWithLabel("Node name:"); nodeNameLabel.setText(CONNECTION_NODE_NAME); SWTBotTreeItem traceRootNode = treeNode.getNode("/rootpath"); traceRootNode.select(); SWTBotText pathLabel = fBot.textWithLabel("Root path:"); pathLabel.setText(TRACE_LOCATION); fBot.checkBox("Recursive").select(); // Add the ctf file pattern treeNode = traceRootNode.getNode(".*"); treeNode.select(); SWTBotText filePatternLabel = fBot.textWithLabel("File pattern:"); filePatternLabel.setText(LTTNG_TRACE_FILE_PATTERN); // Add the syslog file pattern traceRootNode.contextMenu("New Trace").click(); treeNode = traceRootNode.getNode(".*"); treeNode.select(); filePatternLabel = fBot.textWithLabel("File pattern:"); filePatternLabel.setText(SYSLOG_FILE_PATTERN); SWTBotCombo combo = fBot.comboBoxWithLabel("Trace type:"); combo.setSelection("Test trace : Test Syslog"); fBot.button("OK").click(); } private static void testTrace(TmfTraceElement tmfTraceElement, String expectedTracePath, String traceType) { assertEquals(traceType, tmfTraceElement.getTraceType()); IPath tracePath = new Path(tmfTraceElement.getElementPath()); assertEquals(expectedTracePath, tracePath.toString()); SWTBotUtils.openEditor(fBot, PROJECT_NAME, tracePath); } private static void deleteProfile() { openRemoteProfilePreferences(); // The second tree is the remote profiles tree on the right side SWTBotTree tree = fBot.tree(1); SWTBotTreeItem treeNode = tree.getTreeItem(PROFILE_NAME); treeNode.select(); fBot.button("Remove").click(); assertEquals(0, tree.getAllItems().length); fBot.button("OK").click(); } private static SWTBotTreeItem getTreeItem(SWTWorkbenchBot bot, SWTBotTree tree, String... nodeNames) { if (nodeNames.length == 0) { return null; } SWTBotTreeItem currentNode = tree.getTreeItem(nodeNames[0]); for (int i = 1; i < nodeNames.length; i++) { String nodeName = nodeNames[i]; bot.waitUntil(ConditionHelpers.IsTreeChildNodeAvailable(nodeName, currentNode)); SWTBotTreeItem newNode = currentNode.getNode(nodeName); currentNode = newNode; } return currentNode; } private static void openRemoteProfilePreferences() { SWTBotShell preferencesShell = SWTBotUtils.openPreferences(fBot); // The first tree is the preference "categories" on the left side SWTBot bot = preferencesShell.bot(); SWTBotTree tree = bot.tree(0); SWTBotTreeItem treeNode = tree.getTreeItem("Tracing"); treeNode.select(); treeNode.expand(); bot.waitUntil(ConditionHelpers.IsTreeChildNodeAvailable("Remote Profiles", treeNode)); treeNode = treeNode.getNode("Remote Profiles"); treeNode.select(); } private static SWTBotTreeItem getTracesFolderTreeItem(SWTBotView projectExplorerBot) { SWTBotTreeItem treeItem = projectExplorerBot.bot().tree().getTreeItem(PROJECT_NAME); treeItem.select(); treeItem.expand(); return treeItem.getNode("Traces [0]"); } }