From ace6413cbfd37cb5dbfcf36c1afb10d32b338ef5 Mon Sep 17 00:00:00 2001 From: Michael Jeanson Date: Wed, 27 Apr 2016 18:58:58 -0400 Subject: [PATCH] analysis.lami: Add tests for the LAMI JSON protocol parsing Some classes and methods were made more public so that they can be accessed by the test plugin. Bug: 493941 Change-Id: Ida5567a1257cb643962bf357250325eca200b296 Signed-off-by: Michael Jeanson Reviewed-on: https://git.eclipse.org/r/72102 Reviewed-by: Matthew Khouzam Reviewed-by: Hudson CI Reviewed-by: Alexandre Montplaisir Tested-by: Alexandre Montplaisir --- .../META-INF/MANIFEST.MF | 7 +- .../lami/core/tests/LamiAnalysisStub.java | 104 +++++ .../lami/core/tests/LamiJsonParserTest.java | 240 +++++++++++ .../lami/core/tests/package-info.java | 11 - .../testfiles/test-error.json | 4 + .../testfiles/test-metadata.json | 117 ++++++ .../testfiles/test-results.json | 380 ++++++++++++++++++ .../META-INF/MANIFEST.MF | 11 +- .../lami/core/module/LamiAnalysis.java | 44 +- .../analysis/lami/core/types/LamiBitrate.java | 14 +- .../analysis/lami/core/types/LamiSize.java | 14 +- analysis/pom.xml | 1 + 12 files changed, 918 insertions(+), 29 deletions(-) create mode 100644 analysis/org.eclipse.tracecompass.analysis.lami.core.tests/src/org/eclipse/tracecompass/analysis/lami/core/tests/LamiAnalysisStub.java create mode 100644 analysis/org.eclipse.tracecompass.analysis.lami.core.tests/src/org/eclipse/tracecompass/analysis/lami/core/tests/LamiJsonParserTest.java delete mode 100644 analysis/org.eclipse.tracecompass.analysis.lami.core.tests/src/org/eclipse/tracecompass/analysis/lami/core/tests/package-info.java create mode 100644 analysis/org.eclipse.tracecompass.analysis.lami.core.tests/testfiles/test-error.json create mode 100644 analysis/org.eclipse.tracecompass.analysis.lami.core.tests/testfiles/test-metadata.json create mode 100644 analysis/org.eclipse.tracecompass.analysis.lami.core.tests/testfiles/test-results.json diff --git a/analysis/org.eclipse.tracecompass.analysis.lami.core.tests/META-INF/MANIFEST.MF b/analysis/org.eclipse.tracecompass.analysis.lami.core.tests/META-INF/MANIFEST.MF index ae794799fe..9f4f088b57 100644 --- a/analysis/org.eclipse.tracecompass.analysis.lami.core.tests/META-INF/MANIFEST.MF +++ b/analysis/org.eclipse.tracecompass.analysis.lami.core.tests/META-INF/MANIFEST.MF @@ -9,6 +9,11 @@ Bundle-ActivationPolicy: lazy Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Require-Bundle: org.junit;bundle-version="4.0.0", org.eclipse.core.runtime, - org.eclipse.tracecompass.common.core + org.eclipse.core.resources, + org.eclipse.tracecompass.common.core, + org.eclipse.tracecompass.analysis.lami.core, + org.eclipse.tracecompass.tmf.core, + org.eclipse.tracecompass.tmf.core.tests Export-Package: org.eclipse.tracecompass.analysis.lami.core.tests Bundle-Activator: org.eclipse.tracecompass.analysis.lami.core.tests.Activator +Import-Package: com.google.common.collect diff --git a/analysis/org.eclipse.tracecompass.analysis.lami.core.tests/src/org/eclipse/tracecompass/analysis/lami/core/tests/LamiAnalysisStub.java b/analysis/org.eclipse.tracecompass.analysis.lami.core.tests/src/org/eclipse/tracecompass/analysis/lami/core/tests/LamiAnalysisStub.java new file mode 100644 index 0000000000..18aa5dcaef --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.lami.core.tests/src/org/eclipse/tracecompass/analysis/lami/core/tests/LamiAnalysisStub.java @@ -0,0 +1,104 @@ +/******************************************************************************* + * Copyright (c) 2016 EfficiOS Inc., Michael Jeanson + * + * 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 + *******************************************************************************/ + +package org.eclipse.tracecompass.analysis.lami.core.tests; + +import static org.junit.Assert.fail; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URL; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.LamiAnalysis; +import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.LamiChartModel; +import org.eclipse.tracecompass.tmf.core.analysis.ondemand.OnDemandAnalysisException; +import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; + +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.Multimap; + +/** + * Extension of {@link LamiAnalysis} used for tests. + */ +public class LamiAnalysisStub extends LamiAnalysis { + + private final String fMetaDatafilename; + private final String fResultFilename; + + /** + * Constructor. + * + * @param metaDatafilename + * Filename of the JSON metadata file. + * @param resultFilename + * Filename of the JSON results file. + */ + protected LamiAnalysisStub(String metaDatafilename, String resultFilename) { + super("Stub Analysis", false, o -> true, Collections.singletonList("StubExecutable")); + fMetaDatafilename = metaDatafilename; + fResultFilename = resultFilename; + } + + @Override + public @NonNull String getName() { + return "StubName"; + } + + @Override + protected @NonNull Multimap<@NonNull String, @NonNull LamiChartModel> getPredefinedCharts() { + return ImmutableMultimap.of(); + } + + @Override + protected String getResultsFromCommand(List command, IProgressMonitor monitor) + throws OnDemandAnalysisException { + + return readLamiFile(fResultFilename); + } + + @Override + protected @Nullable String getOutputFromCommand(List command) { + return readLamiFile(fMetaDatafilename); + } + + @Override + public boolean canExecute(ITmfTrace trace) { + initialize(); + return true; + } + + @Override + protected synchronized void initialize() { + checkMetadata(); + } + + private static String readLamiFile(String filename) { + String fileContent = ""; + try { + URL url = new URL("platform:/plugin/org.eclipse.tracecompass.analysis.lami.core.tests/testfiles/" + filename); + + try (InputStream inputStream = url.openConnection().getInputStream()) { + BufferedReader in = new BufferedReader(new InputStreamReader(inputStream)); + fileContent = in.lines().collect(Collectors.joining()); + } + } catch (IOException e) { + fail(e.getMessage()); + } + + return fileContent; + } +} diff --git a/analysis/org.eclipse.tracecompass.analysis.lami.core.tests/src/org/eclipse/tracecompass/analysis/lami/core/tests/LamiJsonParserTest.java b/analysis/org.eclipse.tracecompass.analysis.lami.core.tests/src/org/eclipse/tracecompass/analysis/lami/core/tests/LamiJsonParserTest.java new file mode 100644 index 0000000000..6f6acc5cab --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.lami.core.tests/src/org/eclipse/tracecompass/analysis/lami/core/tests/LamiJsonParserTest.java @@ -0,0 +1,240 @@ +/******************************************************************************* + * Copyright (c) 2016 EfficiOS Inc., Michael Jeanson + * + * 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 + *******************************************************************************/ + +package org.eclipse.tracecompass.analysis.lami.core.tests; + +import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull; +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 java.util.List; +import java.util.Map; + +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.aspect.LamiTableEntryAspect; +import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.LamiResultTable; +import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.LamiTableClass; +import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.LamiTableEntry; +import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.types.LamiBitrate; +import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.types.LamiData; +import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.types.LamiDuration; +import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.types.LamiSize; +import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.types.LamiSystemCall; +import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.types.LamiTimeRange; +import org.eclipse.tracecompass.tmf.core.analysis.ondemand.OnDemandAnalysisException; +import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp; +import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimeRange; +import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp; +import org.eclipse.tracecompass.tmf.tests.stubs.trace.TmfTraceStub; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + + +/** + * Test cases to verify the JSON parsing of LamiAnalyses. + */ +public class LamiJsonParserTest { + + private static final double DELTA = 0.001; + + private static final String TRACEPATH = "fake/path/to/trace"; + private LamiTmfTraceStub fTrace; + + /** + * Extend TmfTraceStub to return a fake path. + */ + private static class LamiTmfTraceStub extends TmfTraceStub { + @Override + public String getPath() { + return TRACEPATH; + } + } + + /** + * Test setup + */ + @Before + public void setup() { + fTrace = new LamiTmfTraceStub(); + } + + /** + * Test teardown + */ + @After + public void teardown() { + fTrace.dispose(); + } + + /** + * Test the metadata parsing. + */ + @Test + public void testMetadata() { + LamiAnalysisStub analysis = new LamiAnalysisStub("test-metadata.json", "test-results.json"); + + assertTrue(analysis.canExecute(fTrace)); + assertEquals("LAMI test", analysis.getAnalysisTitle()); + + Map tableModels = analysis.getTableClasses(); + + /* Table models tests */ + assertNotNull(tableModels); + assertFalse(tableModels.isEmpty()); + assertEquals(3, tableModels.size()); + + /* Table class tests */ + LamiTableClass perSyscallClass = tableModels.get("per-syscall"); + assertNotNull(perSyscallClass); + LamiTableClass perProcessClass = tableModels.get("per-proc"); + assertNotNull(perProcessClass); + LamiTableClass perInterruptClass = tableModels.get("per-irq"); + assertNotNull(perInterruptClass); + + assertEquals("Per-syscall stuff", perSyscallClass.getTableTitle()); + assertEquals("Per-process stuff", perProcessClass.getTableTitle()); + assertEquals("Per-interrupt stuff", perInterruptClass.getTableTitle()); + + /* Aspects tests */ + List aspects = perSyscallClass.getAspects(); + + assertFalse(aspects.isEmpty()); + assertEquals(8, aspects.size()); + + assertEquals("System call", aspects.get(0).getLabel()); + assertEquals("Duration (ns)", aspects.get(1).getLabel()); + assertEquals("Size (bytes)", aspects.get(2).getLabel()); + assertEquals("Bitrate (bps)", aspects.get(3).getLabel()); + assertEquals("Time range (begin)", aspects.get(4).getLabel()); + assertEquals("Time range (end)", aspects.get(5).getLabel()); + assertEquals("Time range (duration) (ns)", aspects.get(6).getLabel()); + assertEquals("", aspects.get(7).getLabel()); // Empty aspect to fix SWT display bug + } + + /** + * Test the results parsing. + * + * @throws OnDemandAnalysisException when execute() fails. + */ + @Test + public void testResults() throws OnDemandAnalysisException { + LamiAnalysisStub analysis = new LamiAnalysisStub("test-metadata.json", "test-results.json"); + + List resultTables = analysis.execute(fTrace, null, "", new NullProgressMonitor()); + + assertFalse(resultTables.isEmpty()); + assertEquals(4, resultTables.size()); + + LamiResultTable perProcessTable = resultTables.get(0); + LamiResultTable perSyscallTable = resultTables.get(1); + LamiResultTable perInterruptTable = resultTables.get(2); + LamiResultTable perInterruptOverrideTable = resultTables.get(3); + + assertEquals("Per-process stuff", perProcessTable.getTableClass().getTableTitle()); + assertEquals("per-proc", perProcessTable.getTableClass().getTableClassName()); + + assertEquals("Per-syscall stuff", perSyscallTable.getTableClass().getTableTitle()); + assertEquals("per-syscall", perSyscallTable.getTableClass().getTableClassName()); + + assertEquals("Per-interrupt stuff", perInterruptTable.getTableClass().getTableTitle()); + assertEquals("per-irq", perInterruptTable.getTableClass().getTableClassName()); + + assertEquals("Per-interrupt stuff [with overridden title]", perInterruptOverrideTable.getTableClass().getTableTitle()); + assertEquals("Extended per-irq", perInterruptOverrideTable.getTableClass().getTableClassName()); + + assertEquals(1000, perProcessTable.getTimeRange().getStart()); + assertEquals(2000, perProcessTable.getTimeRange().getEnd()); + assertEquals(1000, perProcessTable.getTimeRange().getDuration()); + + List syscallEntries = perSyscallTable.getEntries(); + + assertFalse(syscallEntries.isEmpty()); + assertEquals(5, syscallEntries.size()); + + LamiTableEntry readEntry = syscallEntries.get(0); + LamiTimeRange readEntryTimeRange = readEntry.getCorrespondingTimeRange(); + + assertNotNull(readEntryTimeRange); + assertEquals(98233, readEntryTimeRange.getStart()); + assertEquals(1293828, readEntryTimeRange.getEnd()); + assertEquals(1195595, readEntryTimeRange.getDuration()); + + + /* Test raw values */ + LamiData value0 = readEntry.getValue(0); + assertTrue(value0 instanceof LamiSystemCall); + assertEquals("read", ((LamiSystemCall) value0).getValue()); + + LamiData value1 = readEntry.getValue(1); + assertTrue(value1 instanceof LamiDuration); + assertEquals(2398123, ((LamiDuration) value1).getValue()); + + LamiData value2 = readEntry.getValue(2); + assertTrue(value2 instanceof LamiSize); + assertEquals(8123982, ((LamiSize) value2).getValue()); + + LamiData value3 = readEntry.getValue(3); + assertTrue(value3 instanceof LamiBitrate); + assertEquals(223232, ((LamiBitrate) value3).getValue()); + + LamiData value4 = readEntry.getValue(4); + assertTrue(value4 instanceof LamiTimeRange); + assertEquals(98233, ((LamiTimeRange) value4).getStart()); + assertEquals(1293828, ((LamiTimeRange) value4).getEnd()); + + + /* Test with aspects */ + Map tableModels = analysis.getTableClasses(); + assertNotNull(tableModels); + LamiTableClass perSyscallClass = tableModels.get("per-syscall"); + assertNotNull(perSyscallClass); + List aspects = perSyscallClass.getAspects(); + + assertEquals("read()", aspects.get(0).resolveString(readEntry)); + assertEquals(2398123.0, checkNotNull(aspects.get(1).resolveDouble(readEntry)).doubleValue(), DELTA); + assertEquals(8123982.0, checkNotNull(aspects.get(2).resolveDouble(readEntry)).doubleValue(), DELTA); + assertEquals(223232.0, checkNotNull(aspects.get(3).resolveDouble(readEntry)).doubleValue(), DELTA); + assertEquals(98233.0, checkNotNull(aspects.get(4).resolveDouble(readEntry)).doubleValue(), DELTA); + assertEquals(1293828.0, checkNotNull(aspects.get(5).resolveDouble(readEntry)).doubleValue(), DELTA); + assertEquals(1195595.0, checkNotNull(aspects.get(6).resolveDouble(readEntry)).doubleValue(), DELTA); + assertNull(aspects.get(7).resolveString(readEntry)); + } + + /** + * Test the error parsing of the results. + * + * @throws OnDemandAnalysisException when execute() fails. + */ + @Test (expected = OnDemandAnalysisException.class) + public void testResultsError() throws OnDemandAnalysisException { + LamiAnalysisStub analysis = new LamiAnalysisStub("test-metadata.json", "test-error.json"); + + analysis.execute(fTrace, null, "", new NullProgressMonitor()); + } + + /** + * Test the command generation. + */ + @Test + public void testBaseCommand() { + LamiAnalysisStub analysis = new LamiAnalysisStub("test-metadata.json", "test-error.json"); + + ITmfTimestamp begin = TmfTimestamp.fromNanos(98233); + ITmfTimestamp end = TmfTimestamp.fromNanos(1293828); + + TmfTimeRange timerange = new TmfTimeRange(begin, end); + + assertEquals("StubExecutable " + '\"' + TRACEPATH + '\"', analysis.getFullCommandAsString(fTrace, null)); + assertEquals("StubExecutable --begin 98233 --end 1293828 " + '\"' + TRACEPATH + '\"', analysis.getFullCommandAsString(fTrace, timerange)); + } +} diff --git a/analysis/org.eclipse.tracecompass.analysis.lami.core.tests/src/org/eclipse/tracecompass/analysis/lami/core/tests/package-info.java b/analysis/org.eclipse.tracecompass.analysis.lami.core.tests/src/org/eclipse/tracecompass/analysis/lami/core/tests/package-info.java deleted file mode 100644 index 18c415da98..0000000000 --- a/analysis/org.eclipse.tracecompass.analysis.lami.core.tests/src/org/eclipse/tracecompass/analysis/lami/core/tests/package-info.java +++ /dev/null @@ -1,11 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2016 EfficiOS Inc., Alexandre Montplaisir - * - * 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 - *******************************************************************************/ - -@org.eclipse.jdt.annotation.NonNullByDefault -package org.eclipse.tracecompass.analysis.lami.core.tests; diff --git a/analysis/org.eclipse.tracecompass.analysis.lami.core.tests/testfiles/test-error.json b/analysis/org.eclipse.tracecompass.analysis.lami.core.tests/testfiles/test-error.json new file mode 100644 index 0000000000..b5787122be --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.lami.core.tests/testfiles/test-error.json @@ -0,0 +1,4 @@ +{ + "error-code": "This is an analysis error!", + "error-message": "analysis" +} diff --git a/analysis/org.eclipse.tracecompass.analysis.lami.core.tests/testfiles/test-metadata.json b/analysis/org.eclipse.tracecompass.analysis.lami.core.tests/testfiles/test-metadata.json new file mode 100644 index 0000000000..412fb40a9b --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.lami.core.tests/testfiles/test-metadata.json @@ -0,0 +1,117 @@ +{ + "table-classes": { + "per-syscall": { + "column-descriptions": [ + { + "title": "System call", + "class": "syscall" + }, + { + "title": "Duration", + "class": "duration" + }, + { + "title": "Size", + "class": "size" + }, + { + "title": "Bitrate", + "class": "bitrate" + }, + { + "title": "Time range", + "class": "time-range" + } + ], + "title": "Per-syscall stuff" + }, + "per-proc": { + "column-descriptions": [ + { + "title": "Process", + "class": "process" + }, + { + "title": "Count", + "unit": "things", + "class": "int" + }, + { + "title": "Flag", + "class": "bool" + }, + { + "title": "Value", + "unit": "thou", + "class": "number" + }, + { + "title": "Name", + "class": "string" + }, + { + "title": "Ratio", + "class": "ratio" + }, + { + "title": "Timestamp", + "class": "timestamp" + } + ], + "title": "Per-process stuff" + }, + "per-irq": { + "column-descriptions": [ + { + "title": "Interrupt", + "class": "irq" + }, + { + "title": "File descriptor", + "class": "fd" + }, + { + "title": "File path", + "class": "path" + }, + { + "title": "CPU", + "class": "cpu" + }, + { + "title": "Disk", + "class": "disk" + }, + { + "title": "Partition", + "class": "part" + }, + { + "title": "Network interface", + "class": "netif" + } + ], + "title": "Per-interrupt stuff" + } + }, + "title": "LAMI test", + "authors": [ + "Phil Proulx" + ], + "description": "LTTng analyses machine interface test", + "version": { + "extra": "dev", + "minor": 2, + "patch": 3, + "major": 1 + }, + "tags": [ + "lami", + "test" + ], + "mi-version": { + "minor": 0, + "major": 1 + }, + "url": "http://perdu.com" +} diff --git a/analysis/org.eclipse.tracecompass.analysis.lami.core.tests/testfiles/test-results.json b/analysis/org.eclipse.tracecompass.analysis.lami.core.tests/testfiles/test-results.json new file mode 100644 index 0000000000..dce78e3dcd --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.lami.core.tests/testfiles/test-results.json @@ -0,0 +1,380 @@ +{ + "results": [ + { + "data": [ + [ + { + "pid": 23, + "name": "zsh", + "class": "process" + }, + 23, + false, + 17.2832, + "typical", + { + "value": 0.154, + "class": "ratio" + }, + { + "value": 817232, + "class": "timestamp" + } + ], + [ + { + "name": "chromium", + "class": "process", + "tid": 4987 + }, + 19, + false, + -19457.15, + "beam", + { + "value": 0.001, + "class": "ratio" + }, + { + "value": 1194875, + "class": "timestamp" + } + ], + [ + { + "name": "terminator", + "class": "process" + }, + -145, + { + "class": "unknown" + }, + 22.22, + "dry", + { + "value": 0.94, + "class": "ratio" + }, + { + "value": 984987658, + "class": "timestamp" + } + ], + [ + { + "pid": 1945, + "class": "process", + "tid": 4497 + }, + 31416, + true, + 17.34, + null, + { + "value": 1.5, + "class": "ratio" + }, + { + "value": 154484512, + "class": "timestamp" + } + ] + ], + "class": "per-proc", + "time-range": { + "end": 2000, + "begin": 1000, + "class": "time-range" + } + }, + { + "data": [ + [ + { + "name": "read", + "class": "syscall" + }, + { + "value": 2398123, + "class": "duration" + }, + { + "value": 8123982, + "class": "size" + }, + { + "value": 223232, + "class": "bitrate" + }, + { + "end": 1293828, + "begin": 98233, + "class": "time-range" + } + ], + [ + { + "name": "write", + "class": "syscall" + }, + { + "value": 412434, + "class": "duration" + }, + { + "value": 5645, + "class": "size" + }, + { + "value": 25235343, + "class": "bitrate" + }, + { + "end": 2354523, + "begin": 5454, + "class": "time-range" + } + ], + [ + { + "name": "sync", + "class": "syscall" + }, + { + "value": 2312454, + "class": "duration" + }, + { + "value": 23433, + "class": "size" + }, + null, + { + "end": 645634545454, + "begin": 12, + "class": "time-range" + } + ], + [ + { + "name": "fstat", + "class": "syscall" + }, + { + "class": "unknown" + }, + { + "value": 2343334, + "class": "size" + }, + { + "value": 5864684, + "class": "bitrate" + }, + { + "end": 645634545, + "begin": 2134, + "class": "time-range" + } + ], + [ + { + "name": "sync", + "class": "syscall" + }, + { + "value": 564533, + "class": "duration" + }, + { + "value": 56875, + "class": "size" + }, + { + "value": 4494494494, + "class": "bitrate" + }, + null + ] + ], + "class": "per-syscall", + "time-range": { + "end": 2000, + "begin": 1000, + "class": "time-range" + } + }, + { + "data": [ + [ + { + "hard": true, + "nr": 15, + "name": "keyboard", + "class": "irq" + }, + { + "fd": 3, + "class": "fd" + }, + { + "path": "/etc/passwd", + "class": "path" + }, + { + "id": 2, + "class": "cpu" + }, + { + "name": "sda", + "class": "disk" + }, + { + "name": "sdb3", + "class": "part" + }, + { + "name": "eth0", + "class": "netif" + } + ], + [ + { + "hard": false, + "nr": 7, + "name": "soft-timer", + "class": "irq" + }, + { + "fd": 1, + "class": "fd" + }, + { + "path": "/dev/null", + "class": "path" + }, + { + "class": "unknown" + }, + { + "name": "hda", + "class": "disk" + }, + { + "name": "mmcblk0p2", + "class": "part" + }, + { + "name": "enp3s25", + "class": "netif" + } + ], + [ + { + "hard": true, + "nr": 34, + "class": "irq" + }, + null, + null, + { + "id": 1, + "class": "cpu" + }, + { + "name": "sdc", + "class": "disk" + }, + { + "name": "sdc3", + "class": "part" + }, + { + "name": "lo", + "class": "netif" + } + ] + ], + "class": "per-irq", + "time-range": { + "end": 2000, + "begin": 1000, + "class": "time-range" + } + }, + { + "data": [ + [ + { + "hard": false, + "nr": 12, + "name": "soft-like-silk", + "class": "irq" + }, + { + "fd": 10, + "class": "fd" + }, + { + "path": "/home/bob/meowmix.txt", + "class": "path" + }, + { + "id": 0, + "class": "cpu" + }, + { + "name": "sdb", + "class": "disk" + }, + { + "name": "sdb2", + "class": "part" + }, + { + "name": "eth1", + "class": "netif" + } + ], + [ + { + "hard": true, + "nr": 1, + "name": "mouse2", + "class": "irq" + }, + { + "fd": 5, + "class": "fd" + }, + null, + { + "id": 7, + "class": "cpu" + }, + { + "name": "vda", + "class": "disk" + }, + { + "name": "vda3", + "class": "part" + }, + { + "name": "wlp3s0", + "class": "netif" + } + ] + ], + "class": { + "inherit": "per-irq", + "title": "Per-interrupt stuff [with overridden title]" + }, + "time-range": { + "end": 2000, + "begin": 1000, + "class": "time-range" + } + } + ] +} diff --git a/analysis/org.eclipse.tracecompass.analysis.lami.core/META-INF/MANIFEST.MF b/analysis/org.eclipse.tracecompass.analysis.lami.core/META-INF/MANIFEST.MF index 1e8f72fef0..907cc770c9 100644 --- a/analysis/org.eclipse.tracecompass.analysis.lami.core/META-INF/MANIFEST.MF +++ b/analysis/org.eclipse.tracecompass.analysis.lami.core/META-INF/MANIFEST.MF @@ -12,10 +12,11 @@ Require-Bundle: org.eclipse.core.runtime, org.eclipse.tracecompass.common.core, org.eclipse.tracecompass.tmf.core Export-Package: org.eclipse.tracecompass.internal.analysis.lami.core;x-internal:=true, - org.eclipse.tracecompass.internal.provisional.analysis.lami.core;x-friends:="org.eclipse.tracecompass.analysis.lami.ui,org.eclipse.tracecompass.lttng2.kernel.core", - org.eclipse.tracecompass.internal.provisional.analysis.lami.core.aspect;x-friends:="org.eclipse.tracecompass.analysis.lami.ui,org.eclipse.tracecompass.lttng2.kernel.core", - org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module;x-friends:="org.eclipse.tracecompass.analysis.lami.ui,org.eclipse.tracecompass.lttng2.kernel.core", - org.eclipse.tracecompass.internal.provisional.analysis.lami.core.types;x-friends:="org.eclipse.tracecompass.analysis.lami.ui,org.eclipse.tracecompass.lttng2.kernel.core" -Import-Package: com.google.common.base, + org.eclipse.tracecompass.internal.provisional.analysis.lami.core;x-friends:="org.eclipse.tracecompass.analysis.lami.ui,org.eclipse.tracecompass.lttng2.kernel.core,org.eclipse.tracecompass.analysis.lami.core.tests", + org.eclipse.tracecompass.internal.provisional.analysis.lami.core.aspect;x-friends:="org.eclipse.tracecompass.analysis.lami.ui,org.eclipse.tracecompass.lttng2.kernel.core,org.eclipse.tracecompass.analysis.lami.core.tests", + org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module;x-friends:="org.eclipse.tracecompass.analysis.lami.ui,org.eclipse.tracecompass.lttng2.kernel.core,org.eclipse.tracecompass.analysis.lami.core.tests", + org.eclipse.tracecompass.internal.provisional.analysis.lami.core.types;x-friends:="org.eclipse.tracecompass.analysis.lami.ui,org.eclipse.tracecompass.lttng2.kernel.core,org.eclipse.tracecompass.analysis.lami.core.tests" +Import-Package: com.google.common.annotations, + com.google.common.base, com.google.common.collect, org.json diff --git a/analysis/org.eclipse.tracecompass.analysis.lami.core/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/core/module/LamiAnalysis.java b/analysis/org.eclipse.tracecompass.analysis.lami.core/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/core/module/LamiAnalysis.java index f11f6c9e5f..5cd62122c6 100644 --- a/analysis/org.eclipse.tracecompass.analysis.lami.core/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/core/module/LamiAnalysis.java +++ b/analysis/org.eclipse.tracecompass.analysis.lami.core/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/core/module/LamiAnalysis.java @@ -61,6 +61,7 @@ import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; +import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMultimap; @@ -141,7 +142,7 @@ public class LamiAnalysis implements IOnDemandAnalysis { } @Override - public boolean appliesTo(ITmfTrace trace) { + public final boolean appliesTo(ITmfTrace trace) { return fAppliesTo.test(trace); } @@ -151,7 +152,12 @@ public class LamiAnalysis implements IOnDemandAnalysis { return fIsAvailable; } - private synchronized void initialize() { + /** + * Perform initialization of the LAMI script. This means verifying that it + * is actually present on disk, and that it returns correct --metadata. + */ + @VisibleForTesting + protected synchronized void initialize() { if (fInitialized) { return; } @@ -174,7 +180,15 @@ public class LamiAnalysis implements IOnDemandAnalysis { fInitialized = true; } - private boolean checkMetadata() { + /** + * Verify that this script returns valid metadata. + * + * This will populate all remaining non-final fields of this class. + * + * @return If the metadata is valid or not + */ + @VisibleForTesting + protected boolean checkMetadata() { /* * The initialize() phase of the analysis will be used to check the * script's metadata. Actual runs of the script will use the execute() @@ -638,9 +652,7 @@ public class LamiAnalysis implements IOnDemandAnalysis { } } catch (JSONException e) { - /* Error parsing the output */ - Activator.instance().logError(nullToEmptyString(e.getMessage())); - return Collections.EMPTY_LIST; + throw new OnDemandAnalysisException(e.getMessage()); } return resultsBuilder.build(); @@ -660,8 +672,14 @@ public class LamiAnalysis implements IOnDemandAnalysis { * Get the output of an external command, used for getting the metadata. * Cannot be cancelled, and will not report errors, simply returns null if * the process ended abnormally. + * + * @param command + * The parameters of the command, passed to + * {@link ProcessBuilder} + * @return The command output as a string */ - private static @Nullable String getOutputFromCommand(List command) { + @VisibleForTesting + protected @Nullable String getOutputFromCommand(List command) { try { ProcessBuilder builder = new ProcessBuilder(command); builder.redirectErrorStream(true); @@ -681,14 +699,20 @@ public class LamiAnalysis implements IOnDemandAnalysis { /** * Get the results of invoking the specified command. * - * The result should start with '{"results":...', as specified by the - * LAMI JSON protocol. The JSON itself may be split over multiple lines. + * The result should start with '{"results":...', as specified by the LAMI + * JSON protocol. The JSON itself may be split over multiple lines. * * @param command * The command to run (program and its arguments) + * @param monitor + * The progress monitor * @return The analysis results + * @throws OnDemandAnalysisException + * If the command ended abnormally, and normal results were not + * returned */ - private static String getResultsFromCommand(List command, IProgressMonitor monitor) + @VisibleForTesting + protected String getResultsFromCommand(List command, IProgressMonitor monitor) throws OnDemandAnalysisException { final int scale = 1000; diff --git a/analysis/org.eclipse.tracecompass.analysis.lami.core/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/core/types/LamiBitrate.java b/analysis/org.eclipse.tracecompass.analysis.lami.core/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/core/types/LamiBitrate.java index 6f490599ea..9b63789932 100644 --- a/analysis/org.eclipse.tracecompass.analysis.lami.core/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/core/types/LamiBitrate.java +++ b/analysis/org.eclipse.tracecompass.analysis.lami.core/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/core/types/LamiBitrate.java @@ -9,7 +9,19 @@ package org.eclipse.tracecompass.internal.provisional.analysis.lami.core.types; -class LamiBitrate extends LamiInteger { +/** + * Class for LAMI 'bitrate' types. + * + * @author Philippe Proulx + */ +public class LamiBitrate extends LamiInteger { + + /** + * Constructor + * + * @param value + * The bitrate value, in bits per second (bps) + */ public LamiBitrate(long value) { super(value); } diff --git a/analysis/org.eclipse.tracecompass.analysis.lami.core/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/core/types/LamiSize.java b/analysis/org.eclipse.tracecompass.analysis.lami.core/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/core/types/LamiSize.java index 0e4d956dfd..c224a879b8 100644 --- a/analysis/org.eclipse.tracecompass.analysis.lami.core/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/core/types/LamiSize.java +++ b/analysis/org.eclipse.tracecompass.analysis.lami.core/src/org/eclipse/tracecompass/internal/provisional/analysis/lami/core/types/LamiSize.java @@ -9,7 +9,19 @@ package org.eclipse.tracecompass.internal.provisional.analysis.lami.core.types; -class LamiSize extends LamiInteger { +/** + * Class for LAMI 'size' types. + * + * @author Philippe Proulx + */ +public class LamiSize extends LamiInteger { + + /** + * Constructor + * + * @param value + * The size value, in bytes + */ public LamiSize(long value) { super(value); } diff --git a/analysis/pom.xml b/analysis/pom.xml index f8be884fc0..ec1f9dd99a 100644 --- a/analysis/pom.xml +++ b/analysis/pom.xml @@ -28,6 +28,7 @@ org.eclipse.tracecompass.analysis.graph.core org.eclipse.tracecompass.analysis.graph.core.tests org.eclipse.tracecompass.analysis.lami.core + org.eclipse.tracecompass.analysis.lami.core.tests org.eclipse.tracecompass.analysis.lami.ui org.eclipse.tracecompass.analysis.graph.ui org.eclipse.tracecompass.analysis.os.linux.core -- 2.34.1