From a3d7df191eafdd33cb2dcc9e6a685589440cf130 Mon Sep 17 00:00:00 2001 From: Bernd Hufmann Date: Fri, 24 Oct 2014 20:41:32 -0400 Subject: [PATCH] lttng: add some stress test for opening and closing of traces This will trigger concurrent starting and cancelling of analyses. After fixing bug 447434 (commit e1c415) this test should run without exceptions. Change-Id: I9c7a35d29e0c4a406511ec1e8032b3d818498b94 Signed-off-by: Bernd Hufmann Reviewed-on: https://git.eclipse.org/r/35508 Tested-by: Hudson CI Reviewed-by: Genevieve Bastien Reviewed-by: Bernd Hufmann --- .../kernel/ui/swtbot/tests/AllTests.java | 3 +- .../ui/swtbot/tests/OpenTraceStressTest.java | 181 ++++++++++++++++++ .../tmf/ui/swtbot/tests/SWTBotUtil.java | 23 ++- 3 files changed, 204 insertions(+), 3 deletions(-) create mode 100644 org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/OpenTraceStressTest.java diff --git a/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/AllTests.java b/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/AllTests.java index 321898014c..26c37091c6 100644 --- a/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/AllTests.java +++ b/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/AllTests.java @@ -21,7 +21,8 @@ import org.junit.runners.Suite; @RunWith(Suite.class) @Suite.SuiteClasses({ ImportAndReadKernelSmokeTest.class, - KernelPerspectiveChecker.class + KernelPerspectiveChecker.class, + OpenTraceStressTest.class }) public class AllTests { diff --git a/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/OpenTraceStressTest.java b/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/OpenTraceStressTest.java new file mode 100644 index 0000000000..af84f2805e --- /dev/null +++ b/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/OpenTraceStressTest.java @@ -0,0 +1,181 @@ +/******************************************************************************* + * Copyright (c) 2014 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: + * Bernd Hufmann - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; +import static org.junit.Assume.assumeTrue; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.PrintStream; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.MultiStatus; +import org.eclipse.core.runtime.jobs.IJobChangeEvent; +import org.eclipse.core.runtime.jobs.IJobManager; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.core.runtime.jobs.JobChangeAdapter; +import org.eclipse.osgi.util.NLS; +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.tracecompass.tmf.core.analysis.Messages; +import org.eclipse.tracecompass.tmf.ctf.core.tests.shared.CtfTmfTestTrace; +import org.eclipse.tracecompass.tmf.ui.swtbot.tests.SWTBotUtil; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * SWTBot stress test for opening and closing of traces. + * + * @author Bernd Hufmann + */ +@RunWith(SWTBotJunit4ClassRunner.class) +public class OpenTraceStressTest { + + 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 CtfTmfTestTrace CTF_TRACE = CtfTmfTestTrace.SYNC_DEST; + private static final String TRACE_PROJECT_NAME = "test"; + + private static SWTWorkbenchBot workbenchbot; + + /** + * Test Class setup + */ + @BeforeClass + public static void init() { + SWTBotUtil.failIfUIThread(); + + /* Set up for swtbot */ + SWTBotPreferences.TIMEOUT = 20000; /* 20 second timeout */ + + workbenchbot = new SWTWorkbenchBot(); + + /* Close welcome view */ + SWTBotUtil.closeView("Welcome", workbenchbot); + + /* Switch perspectives */ + SWTBotUtil.switchToPerspective(KERNEL_PERSPECTIVE_ID); + + /* Finish waiting for eclipse to load */ + SWTBotUtil.waitForJobs(); + } + + /** + * Main test case to test opening and closing of traces concurrently. + */ + @Test + public void testOpenAndCloseConcurrency() { + SWTBotUtil.createProject(TRACE_PROJECT_NAME); + + File fTestFile = new File(CTF_TRACE.getPath()); + + String path = fTestFile.getAbsolutePath(); + + assertNotNull(fTestFile); + assumeTrue(fTestFile.exists()); + + /* + * This opening and closing of traces will trigger several threads for analysis which + * will be closed concurrently. There used to be a concurrency bug (447434) which should + * be fixed by now and this test should run without any exceptions. + * + * Since the failure depends on timing it only happened sometimes before the bug fix + * using this test. + */ + final MultiStatus status = new MultiStatus("lttn2.kernel.ui.swtbot.tests", IStatus.OK, null, null); + IJobManager mgr = Job.getJobManager(); + JobChangeAdapter changeListener = new JobChangeAdapter() { + @Override + public void done(IJobChangeEvent event) { + Job job = event.getJob(); + // Check for analysis failure + String jobNamePrefix = NLS.bind(Messages.TmfAbstractAnalysisModule_RunningAnalysis, ""); + if ((job.getName().startsWith(jobNamePrefix)) && (job.getResult().getSeverity() == IStatus.ERROR)) { + status.add(job.getResult()); + } + } + }; + mgr.addJobChangeListener(changeListener); + for (int i = 0; i < 10; i++) { + SWTBotUtil.openTrace(TRACE_PROJECT_NAME, path, TRACE_TYPE, false); + SWTBotUtil.openTrace(TRACE_PROJECT_NAME, path, TRACE_TYPE, false); + SWTBotUtil.openTrace(TRACE_PROJECT_NAME, path, TRACE_TYPE, false); + SWTBotUtil.openTrace(TRACE_PROJECT_NAME, path, TRACE_TYPE, false); + SWTBotUtil.openTrace(TRACE_PROJECT_NAME, path, TRACE_TYPE, false); + // Add little delay so that treads have a chance to start + SWTBotUtil.delay(1000); + workbenchbot.closeAllEditors(); + + if (!status.isOK()) { + SWTBotUtil.deleteProject(TRACE_PROJECT_NAME, workbenchbot); + fail(handleErrorStatus(status)); + } + } + SWTBotUtil.deleteProject(TRACE_PROJECT_NAME, workbenchbot); + } + + private static String handleErrorStatus(MultiStatus status) { + + // Build a string with all the children status messages, exception + // messages and stack traces + StringBuilder sb = new StringBuilder(); + for (IStatus childStatus : status.getChildren()) { + StringBuilder childSb = new StringBuilder(); + if (!childStatus.getMessage().isEmpty()) { + childSb.append(childStatus.getMessage() + '\n'); + } + + Throwable childException = childStatus.getException(); + if (childException != null) { + String reason = childException.getMessage(); + // Some system exceptions have no message + if (reason == null) { + reason = childException.toString(); + } + + String stackMessage = getExceptionStackMessage(childException); + if (stackMessage == null) { + stackMessage = reason; + } + + childSb.append(stackMessage); + } + + if (childSb.length() > 0) { + childSb.insert(0, '\n'); + sb.append(childSb.toString()); + } + } + return sb.toString(); + } + + private static String getExceptionStackMessage(Throwable exception) { + String stackMessage = null; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + PrintStream ps = new PrintStream(baos); + exception.printStackTrace(ps); + ps.flush(); + try { + baos.flush(); + stackMessage = baos.toString(); + } catch (IOException e) { + } + + return stackMessage; + } +} \ No newline at end of file diff --git a/org.eclipse.tracecompass.tmf.ui.swtbot.tests/src/org/eclipse/tracecompass/tmf/ui/swtbot/tests/SWTBotUtil.java b/org.eclipse.tracecompass.tmf.ui.swtbot.tests/src/org/eclipse/tracecompass/tmf/ui/swtbot/tests/SWTBotUtil.java index fab54d6e64..7ce4c6468a 100644 --- a/org.eclipse.tracecompass.tmf.ui.swtbot.tests/src/org/eclipse/tracecompass/tmf/ui/swtbot/tests/SWTBotUtil.java +++ b/org.eclipse.tracecompass.tmf.ui.swtbot.tests/src/org/eclipse/tracecompass/tmf/ui/swtbot/tests/SWTBotUtil.java @@ -223,6 +223,23 @@ public abstract class SWTBotUtil { * org.eclipse.linuxtools.btf.trace) */ public static void openTrace(final String projectName, final String tracePath, final String traceType) { + openTrace(projectName, tracePath, traceType, true); + } + + /** + * Open a trace, this does not perform any validation though + * + * @param projectName + * The project name + * @param tracePath + * the path of the trace file (absolute or relative) + * @param traceType + * the trace canonical string (eg: + * org.eclipse.linuxtools.btf.trace) + * @param delay + * delay and wait for jobs + */ + public static void openTrace(final String projectName, final String tracePath, final String traceType, boolean delay) { final Exception exception[] = new Exception[1]; exception[0] = null; UIThreadRunnable.syncExec(new VoidResult() { @@ -241,8 +258,10 @@ public abstract class SWTBotUtil { fail(exception[0].getMessage()); } - delay(1000); - waitForJobs(); + if (delay) { + delay(1000); + waitForJobs(); + } } /** -- 2.34.1