And state system analyses can fail when their event requests failed.
Change-Id: Id3bcaf88378cd16e8f0f7ac7aa4d2f0c7c574392
Signed-off-by: Geneviève Bastien <gbastien+lttng@versatic.net>
Reviewed-on: https://git.eclipse.org/r/84037
Reviewed-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Tested-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Reviewed-by: Hudson CI
module2.dispose();
}
}
+
+ /**
+ * Test that an analysis whose event request throws an exception is failed
+ * correctly
+ *
+ * @throws TmfAnalysisException
+ * Propagates exceptions
+ */
+ @Test
+ public void testRequestFailure() throws TmfAnalysisException {
+ TestStateSystemModule module = new TestStateSystemModule();
+ module.setRequestAction(e -> {
+ throw new IllegalArgumentException("This exception is desired and part of the test");
+ });
+ try {
+ ITmfTrace trace = fTrace;
+ assertNotNull(trace);
+ module.setTrace(trace);
+
+ // Execute the module that should throw the exception
+ module.schedule();
+ assertFalse(module.waitForCompletion());
+
+ } finally {
+ module.dispose();
+ }
+ }
}
import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
import java.io.File;
+import java.util.function.Function;
+import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.common.core.NonNullUtils;
+import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
+import org.eclipse.tracecompass.tmf.core.request.ITmfEventRequest;
import org.eclipse.tracecompass.tmf.core.statesystem.ITmfStateProvider;
import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule;
+import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimeRange;
/**
* Test State System module
@NonNullByDefault
public class TestStateSystemModule extends TmfStateSystemAnalysisModule {
- private @Nullable TestStateSystemProvider fProvider = null;
- private boolean fThrottleEvents = false;
private final boolean fOnDisk;
+ private boolean fThrottleEvents = false;
+ private @Nullable TestStateSystemProvider fProvider = null;
+ private Function<ITmfEvent, ITmfEvent> fRequestAction = e -> e;
/**
* Constructor
return super.getSsFile();
}
+ /**
+ * Set a function that will be executed on an event and return an event.
+ * This action will be executed in the event request, before calling the
+ * parent's handleData method.
+ *
+ * @param requestAction
+ * The function to execute on the event
+ */
+ public void setRequestAction(Function<ITmfEvent, ITmfEvent> requestAction) {
+ fRequestAction = requestAction;
+ }
+
+ @Override
+ protected @NonNull ITmfEventRequest createEventRequest(@NonNull ITmfStateProvider stateProvider, @NonNull TmfTimeRange timeRange, int nbRead) {
+ return new TestStateSystemRequest(stateProvider, timeRange, nbRead, fRequestAction);
+ }
+
+ private class TestStateSystemRequest extends StateSystemEventRequest {
+
+ private final Function<ITmfEvent, ITmfEvent> fAction;
+
+ public TestStateSystemRequest(ITmfStateProvider sp, TmfTimeRange timeRange, int index, Function<ITmfEvent, ITmfEvent> requestAction) {
+ super(sp, timeRange, index);
+ fAction = requestAction;
+ }
+
+ @Override
+ public void handleData(final ITmfEvent event) {
+ ITmfEvent ev = NonNullUtils.checkNotNull(fAction.apply(event));
+ super.handleData(ev);
+ }
+
+ }
+
}
*/
void cancel();
+ /**
+ * Makes the analysis fail with a cause
+ *
+ * @param cause The cause of the failure
+ * @since 2.3
+ */
+ default void fail(@NonNull Throwable cause) {
+ // Do nothing by default.
+ }
+
// -----------------------------------------------------
// Utilities
// -----------------------------------------------------
private boolean fAnalysisCancelled = false;
+ private @Nullable Throwable fFailureCause = null;
+
@Override
public boolean isAutomatic() {
return fAutomatic;
}
}
+ /**
+ * @since 2.3
+ */
+ @Override
+ public final void fail(Throwable cause) {
+ fFailureCause = cause;
+ }
+
@Override
public void dispose() {
super.dispose();
} catch (InterruptedException e) {
Activator.logError("Error while waiting for module completion", e); //$NON-NLS-1$
}
- return !fAnalysisCancelled;
+ return (!fAnalysisCancelled && fFailureCause == null);
}
@Override
} catch (InterruptedException e) {
Activator.logError("Error while waiting for module completion", e); //$NON-NLS-1$
}
- return !fAnalysisCancelled;
+ return (!fAnalysisCancelled && fFailureCause == null);
}
/**
fStateProvider = provider;
synchronized (fRequestSyncObj) {
startRequest();
+ request = fRequest;
}
/*
* progress monitor displays that it is running).
*/
try {
- if (fRequest != null) {
- fRequest.waitForCompletion();
+ if (request != null) {
+ request.waitForCompletion();
+ if (request.isFailed()) {
+ Throwable failureCause = request.getFailureCause();
+ if (failureCause != null) {
+ fail(failureCause);
+ } else {
+ fail(new RuntimeException("Event request failed without a cause")); //$NON-NLS-1$
+ }
+ }
}
} catch (InterruptedException e) {
- e.printStackTrace();
+ fail(e);
}
}
- private class StateSystemEventRequest extends TmfEventRequest {
+ /**
+ * A request to build a state system from a state provider
+ *
+ * @since 2.3
+ */
+ @VisibleForTesting
+ protected class StateSystemEventRequest extends TmfEventRequest {
private final ITmfStateProvider sci;
private final ITmfTrace trace;
+ /**
+ * Constructor
+ *
+ * @param sp
+ * The state provider used to build the state system
+ * @param timeRange
+ * The requested time range for the request
+ * @param index
+ * The event number at which to start the request
+ */
public StateSystemEventRequest(ITmfStateProvider sp, TmfTimeRange timeRange, int index) {
super(ITmfEvent.class,
timeRange,
if (stateProvider == null || timeRange == null) {
return;
}
- ITmfEventRequest request = new StateSystemEventRequest(stateProvider, timeRange, fNbRead);
+ ITmfEventRequest request = createEventRequest(stateProvider, timeRange, fNbRead);
stateProvider.getTrace().sendRequest(request);
fRequest = request;
}
+ /**
+ * Create a new event request
+ *
+ * @param stateProvider
+ * The state provider used to build the state system
+ * @param timeRange
+ * The requested time range for the request
+ * @param nbRead
+ * The event number at which to start the request
+ * @return A new event request
+ * @since 2.3
+ */
+ @VisibleForTesting
+ protected ITmfEventRequest createEventRequest(ITmfStateProvider stateProvider, TmfTimeRange timeRange, int nbRead) {
+ return new StateSystemEventRequest(stateProvider, timeRange, nbRead);
+ }
+
private static boolean isCompleteTrace(ITmfTrace trace) {
return !(trace instanceof ITmfTraceCompleteness) || ((ITmfTraceCompleteness) trace).isComplete();
}