blob: f86559143cd6e806258c771a27d5734b097725f7 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2014, 2019 Ericsson
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License 2.0 which
* accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* 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.jdt.annotation.NonNull;
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.testtraces.ctf.CtfTestTrace;
import org.eclipse.tracecompass.tmf.core.analysis.Messages;
import org.eclipse.tracecompass.tmf.ctf.core.tests.shared.CtfTmfTestTraceUtils;
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;
/**
* 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 @NonNull CtfTestTrace CTF_TRACE = CtfTestTrace.SYNC_DEST;
private static final String TRACE_PROJECT_NAME = "test";
private static SWTWorkbenchBot workbenchbot;
/**
* Test Class setup
*/
@BeforeClass
public static void init() {
SWTBotUtils.initialize();
/* Set up for swtbot */
SWTBotPreferences.TIMEOUT = 20000; /* 20 second timeout */
workbenchbot = new SWTWorkbenchBot();
/* Close welcome view */
SWTBotUtils.closeView("Welcome", workbenchbot);
/* Switch perspectives */
SWTBotUtils.switchToPerspective(KERNEL_PERSPECTIVE_ID);
/* Finish waiting for eclipse to load */
WaitUtils.waitForJobs();
}
/**
* Main test case to test opening and closing of traces concurrently.
*/
@Test
public void testOpenAndCloseConcurrency() {
SWTBotUtils.createProject(TRACE_PROJECT_NAME);
File fTestFile = new File(CtfTmfTestTraceUtils.getTrace(CTF_TRACE).getPath());
CtfTmfTestTraceUtils.dispose(CTF_TRACE);
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++) {
SWTBotUtils.openTrace(TRACE_PROJECT_NAME, path, TRACE_TYPE, false);
SWTBotUtils.openTrace(TRACE_PROJECT_NAME, path, TRACE_TYPE, false);
SWTBotUtils.openTrace(TRACE_PROJECT_NAME, path, TRACE_TYPE, false);
SWTBotUtils.openTrace(TRACE_PROJECT_NAME, path, TRACE_TYPE, false);
SWTBotUtils.openTrace(TRACE_PROJECT_NAME, path, TRACE_TYPE, false);
// Wait for editor so that threads have a chance to start
workbenchbot.editorByTitle(fTestFile.getName());
workbenchbot.closeAllEditors();
if (!status.isOK()) {
SWTBotUtils.deleteProject(TRACE_PROJECT_NAME, workbenchbot);
fail(handleErrorStatus(status));
}
}
SWTBotUtils.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;
}
}