| /******************************************************************************* |
| * Copyright (c) 2013, 2014 École Polytechnique de Montréal |
| * |
| * 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: |
| * Geneviève Bastien - Initial API and implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.tracecompass.tmf.core.tests.analysis; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertFalse; |
| import static org.junit.Assert.assertNotNull; |
| import static org.junit.Assert.assertNull; |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.Assert.fail; |
| |
| import java.util.HashSet; |
| import java.util.Set; |
| import java.util.concurrent.TimeUnit; |
| |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.jdt.annotation.NonNull; |
| import org.eclipse.osgi.util.NLS; |
| import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModule; |
| import org.eclipse.tracecompass.tmf.core.analysis.Messages; |
| import org.eclipse.tracecompass.tmf.core.analysis.TmfAbstractAnalysisModule; |
| import org.eclipse.tracecompass.tmf.core.exceptions.TmfAnalysisException; |
| import org.eclipse.tracecompass.tmf.core.tests.shared.TmfTestHelper; |
| import org.eclipse.tracecompass.tmf.core.tests.shared.TmfTestTrace; |
| import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; |
| import org.eclipse.tracecompass.tmf.tests.stubs.analysis.TestAnalysis; |
| import org.eclipse.tracecompass.tmf.tests.stubs.analysis.TestAnalysis2; |
| import org.junit.After; |
| import org.junit.Rule; |
| import org.junit.Test; |
| import org.junit.rules.TestRule; |
| import org.junit.rules.Timeout; |
| |
| import com.google.common.collect.ImmutableSet; |
| |
| /** |
| * Test suite for the {@link TmfAbstractAnalysisModule} class |
| */ |
| public class AnalysisModuleTest { |
| |
| /** Test timeout */ |
| @Rule |
| public TestRule timeoutRule = new Timeout(1, TimeUnit.MINUTES); |
| |
| private static final @NonNull String MODULE_GENERIC_ID = "test.id"; |
| private static final @NonNull String MODULE_GENERIC_NAME = "Test analysis"; |
| |
| /** |
| * Some tests use traces, let's clean them here |
| */ |
| @After |
| public void cleanupTraces() { |
| TmfTestTrace.A_TEST_10K.dispose(); |
| } |
| |
| /** |
| * Test suite for analysis module getters and setters |
| */ |
| @Test |
| public void testGettersSetters() { |
| IAnalysisModule module = new TestAnalysis(); |
| |
| module.setName(MODULE_GENERIC_NAME); |
| module.setId(MODULE_GENERIC_ID); |
| assertEquals(MODULE_GENERIC_ID, module.getId()); |
| assertEquals(MODULE_GENERIC_NAME, module.getName()); |
| |
| module.setAutomatic(false); |
| assertFalse(module.isAutomatic()); |
| module.setAutomatic(true); |
| assertTrue(module.isAutomatic()); |
| module.addParameter(TestAnalysis.PARAM_TEST); |
| assertNull(module.getParameter(TestAnalysis.PARAM_TEST)); |
| module.setParameter(TestAnalysis.PARAM_TEST, 1); |
| assertEquals(1, module.getParameter(TestAnalysis.PARAM_TEST)); |
| |
| assertEquals(0, module.getDependencyLevel()); |
| |
| /* Try to set and get wrong parameter */ |
| String wrongParam = "abc"; |
| Exception exception = null; |
| try { |
| module.setParameter(wrongParam, 1); |
| } catch (RuntimeException e) { |
| exception = e; |
| assertEquals(NLS.bind(Messages.TmfAbstractAnalysisModule_InvalidParameter, wrongParam, module.getName()), e.getMessage()); |
| } |
| assertNotNull(exception); |
| assertNull(module.getParameter(wrongParam)); |
| |
| module.dispose(); |
| } |
| |
| private static TestAnalysis setUpAnalysis() { |
| TestAnalysis module = new TestAnalysis(); |
| |
| module.setName(MODULE_GENERIC_NAME); |
| module.setId(MODULE_GENERIC_ID); |
| module.addParameter(TestAnalysis.PARAM_TEST); |
| |
| return module; |
| } |
| |
| /** |
| * Test suite for analysis module |
| * {@link TmfAbstractAnalysisModule#waitForCompletion} with successful |
| * execution |
| */ |
| @Test |
| public void testWaitForCompletionSuccess() { |
| TestAnalysis module = setUpAnalysis(); |
| |
| IStatus status = module.schedule(); |
| assertEquals(IStatus.ERROR, status.getSeverity()); |
| |
| /* Set a stub trace for analysis */ |
| try { |
| assertTrue(module.setTrace(TmfTestTrace.A_TEST_10K.getTrace())); |
| } catch (TmfAnalysisException e) { |
| fail(e.getMessage()); |
| } |
| |
| /* Default execution, with output 1 */ |
| module.setParameter(TestAnalysis.PARAM_TEST, 1); |
| status = module.schedule(); |
| assertEquals(Status.OK_STATUS, status); |
| boolean completed = module.waitForCompletion(); |
| |
| assertTrue(completed); |
| assertEquals(1, module.getAnalysisOutput()); |
| |
| module.dispose(); |
| } |
| |
| /** |
| * Test suite for {@link TmfAbstractAnalysisModule#waitForCompletion} with |
| * cancellation |
| */ |
| @Test |
| public void testWaitForCompletionCancelled() { |
| TestAnalysis module = setUpAnalysis(); |
| try { |
| /* Set a stub trace for analysis */ |
| ITmfTrace trace = TmfTestTrace.A_TEST_10K.getTrace(); |
| try { |
| assertTrue(module.setTrace(trace)); |
| } catch (TmfAnalysisException e) { |
| fail(e.getMessage()); |
| } |
| |
| module.setParameter(TestAnalysis.PARAM_TEST, 0); |
| IStatus status = module.schedule(); |
| assertEquals(Status.OK_STATUS, status); |
| boolean completed = module.waitForCompletion(); |
| |
| assertFalse(completed); |
| assertEquals(0, module.getAnalysisOutput()); |
| } finally { |
| module.dispose(); |
| } |
| } |
| |
| /** |
| * Test the {@link TmfAbstractAnalysisModule#setTrace(ITmfTrace)} method |
| * with wrong trace |
| */ |
| @Test |
| public void testSetWrongTrace() { |
| IAnalysisModule module = new TestAnalysis2(); |
| |
| module.setName(MODULE_GENERIC_NAME); |
| module.setId(MODULE_GENERIC_ID); |
| assertEquals(MODULE_GENERIC_ID, module.getId()); |
| assertEquals(MODULE_GENERIC_NAME, module.getName()); |
| |
| try { |
| assertFalse(module.setTrace(TmfTestTrace.A_TEST_10K.getTrace())); |
| } catch (TmfAnalysisException e) { |
| fail(); |
| } |
| |
| module.dispose(); |
| } |
| |
| /** |
| * Test the {@link TmfAbstractAnalysisModule#setTrace(ITmfTrace)} method |
| * with wrong trace |
| */ |
| @Test |
| public void testSetTraceTwice() { |
| IAnalysisModule module = new TestAnalysis(); |
| |
| module.setName(MODULE_GENERIC_NAME); |
| module.setId(MODULE_GENERIC_ID); |
| |
| try { |
| assertTrue(module.setTrace(TmfTestTrace.A_TEST_10K.getTrace())); |
| } catch (TmfAnalysisException e) { |
| fail(); |
| } |
| TmfAnalysisException exception = null; |
| try { |
| module.setTrace(TmfTestTrace.A_TEST_10K.getTrace()); |
| } catch (TmfAnalysisException e) { |
| exception = e; |
| } |
| assertNotNull(exception); |
| |
| module.dispose(); |
| } |
| |
| /** |
| * Test suite for the {@link TmfAbstractAnalysisModule#cancel()} method |
| */ |
| @Test |
| public void testCancel() { |
| TestAnalysis module = setUpAnalysis(); |
| |
| module.setParameter(TestAnalysis.PARAM_TEST, 999); |
| try { |
| assertTrue(module.setTrace(TmfTestTrace.A_TEST_10K.getTrace())); |
| } catch (TmfAnalysisException e) { |
| fail(e.getMessage()); |
| } |
| |
| IStatus schedule = module.schedule(); |
| assertEquals(Status.OK_STATUS, schedule); |
| |
| /* Give the job a chance to start */ |
| try { |
| Thread.sleep(1000); |
| } catch (InterruptedException e) { |
| fail(e.getMessage()); |
| } |
| |
| module.cancel(); |
| assertFalse(module.waitForCompletion()); |
| assertEquals(-1, module.getAnalysisOutput()); |
| |
| module.dispose(); |
| } |
| |
| /** |
| * Test suite for the {@link IAnalysisModule#notifyParameterChanged(String)} |
| * method |
| */ |
| @Test |
| public void testParameterChanged() { |
| TestAnalysis module = setUpAnalysis(); |
| |
| try { |
| assertTrue(module.setTrace(TmfTestTrace.A_TEST_10K.getTrace())); |
| } catch (TmfAnalysisException e) { |
| fail(e.getMessage()); |
| } |
| |
| /* Check exception if no wrong parameter name */ |
| Exception exception = null; |
| try { |
| module.notifyParameterChanged("aaa"); |
| } catch (RuntimeException e) { |
| exception = e; |
| } |
| assertNotNull(exception); |
| |
| /* |
| * Cannot test anymore of this method, need a parameter provider to do |
| * this |
| */ |
| module.dispose(); |
| } |
| |
| /** |
| * Test the {@link TmfTestHelper#executeAnalysis(IAnalysisModule)} method |
| */ |
| @Test |
| public void testHelper() { |
| TestAnalysis module = setUpAnalysis(); |
| |
| try { |
| assertTrue(module.setTrace(TmfTestTrace.A_TEST_10K.getTrace())); |
| } catch (TmfAnalysisException e) { |
| fail(e.getMessage()); |
| } |
| |
| module.setParameter(TestAnalysis.PARAM_TEST, 1); |
| boolean res = TmfTestHelper.executeAnalysis(module); |
| assertTrue(res); |
| |
| module.setParameter(TestAnalysis.PARAM_TEST, 0); |
| res = TmfTestHelper.executeAnalysis(module); |
| assertFalse(res); |
| |
| module.dispose(); |
| } |
| |
| /** |
| * Test the {@link TmfAbstractAnalysisModule} also executes the dependent |
| * analyses |
| */ |
| @Test |
| public void testDependentAnalyses() { |
| |
| ITmfTrace trace = TmfTestTrace.A_TEST_10K.getTrace(); |
| int paramAndResult = 5; |
| |
| /* Setup the dependent module */ |
| final String suffix = " dep"; |
| final TestAnalysis depModule = new TestAnalysis() { |
| |
| @Override |
| protected boolean executeAnalysis(IProgressMonitor monitor) { |
| try { |
| Thread.sleep(1000); |
| } catch (InterruptedException e) { |
| return false; |
| } |
| return super.executeAnalysis(monitor); |
| } |
| |
| }; |
| depModule.setName(MODULE_GENERIC_NAME + suffix); |
| depModule.setId(MODULE_GENERIC_ID + suffix); |
| depModule.addParameter(TestAnalysis.PARAM_TEST); |
| depModule.setParameter(TestAnalysis.PARAM_TEST, paramAndResult); |
| |
| /* Prepare the main analysis with a dependent analysis */ |
| TestAnalysis module = new TestAnalysis() { |
| |
| @Override |
| protected Iterable<IAnalysisModule> getDependentAnalyses() { |
| Set<IAnalysisModule> modules = new HashSet<>(); |
| modules.add(depModule); |
| return modules; |
| } |
| |
| }; |
| |
| module.setName(MODULE_GENERIC_NAME); |
| module.setId(MODULE_GENERIC_ID); |
| module.addParameter(TestAnalysis.PARAM_TEST); |
| module.setParameter(TestAnalysis.PARAM_TEST, paramAndResult); |
| |
| try { |
| assertTrue(depModule.setTrace(trace)); |
| assertTrue(module.setTrace(trace)); |
| } catch (TmfAnalysisException e) { |
| fail(e.getMessage()); |
| } |
| |
| /* Verify none of the module has run */ |
| assertEquals(0, module.getAnalysisOutput()); |
| assertEquals(0, depModule.getAnalysisOutput()); |
| |
| module.schedule(); |
| assertTrue(module.waitForCompletion()); |
| assertEquals(paramAndResult, module.getAnalysisOutput()); |
| |
| /* Make sure the dependent analysis has run and completed */ |
| assertEquals(paramAndResult, depModule.getAnalysisOutput()); |
| |
| /* Check the dependency level of both analyses */ |
| assertEquals(0, depModule.getDependencyLevel()); |
| assertEquals(1, module.getDependencyLevel()); |
| |
| module.dispose(); |
| depModule.dispose(); |
| trace.dispose(); |
| |
| } |
| |
| /** |
| * Test that the dependency level is consistent with a case where |
| * B depends on A, and C depends on A and B |
| */ |
| @Test |
| public void testMultipleDependencies() { |
| |
| ITmfTrace trace = TmfTestTrace.A_TEST_10K.getTrace(); |
| |
| /* Prepare module A with no dependency */ |
| IAnalysisModule moduleA = new TestAnalysis(); |
| moduleA.setName(MODULE_GENERIC_NAME); |
| moduleA.setId(MODULE_GENERIC_ID); |
| moduleA.addParameter(TestAnalysis.PARAM_TEST); |
| moduleA.setParameter(TestAnalysis.PARAM_TEST, 1); |
| |
| /* Prepare module B depending on A */ |
| String suffix = " B"; |
| IAnalysisModule moduleB = new TestAnalysis() { |
| |
| @Override |
| protected Iterable<IAnalysisModule> getDependentAnalyses() { |
| return ImmutableSet.of(moduleA); |
| } |
| |
| }; |
| moduleB.setName(MODULE_GENERIC_NAME + suffix); |
| moduleB.setId(MODULE_GENERIC_ID + suffix); |
| moduleB.addParameter(TestAnalysis.PARAM_TEST); |
| moduleB.setParameter(TestAnalysis.PARAM_TEST, 1); |
| |
| /* Prepare module C depending on A and B */ |
| suffix = " C"; |
| IAnalysisModule moduleC = new TestAnalysis() { |
| |
| @Override |
| protected Iterable<IAnalysisModule> getDependentAnalyses() { |
| return ImmutableSet.of(moduleA, moduleB); |
| } |
| |
| }; |
| moduleC.setName(MODULE_GENERIC_NAME + suffix); |
| moduleC.setId(MODULE_GENERIC_ID + suffix); |
| moduleC.addParameter(TestAnalysis.PARAM_TEST); |
| moduleC.setParameter(TestAnalysis.PARAM_TEST, 1); |
| |
| try { |
| assertTrue(moduleA.setTrace(trace)); |
| assertTrue(moduleB.setTrace(trace)); |
| assertTrue(moduleC.setTrace(trace)); |
| } catch (TmfAnalysisException e) { |
| fail(e.getMessage()); |
| } |
| |
| moduleC.schedule(); |
| assertTrue(moduleC.waitForCompletion()); |
| |
| /* Check the dependency level of the analyses */ |
| assertEquals(0, moduleA.getDependencyLevel()); |
| assertEquals(1, moduleB.getDependencyLevel()); |
| assertEquals(3, moduleC.getDependencyLevel()); |
| |
| moduleA.dispose(); |
| moduleB.dispose(); |
| moduleC.dispose(); |
| trace.dispose(); |
| |
| } |
| } |