--- /dev/null
+/*******************************************************************************
+ * 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