server: serialize ITmfXyEntryModel specific attributes Add unit tests that queries the histogram data provider which uses the new API. With this the serialization of the new boolean flag is tested. Bug 581326 [Added] Serialization of ITmfXyEntryModel specific attributes Change-Id: I226c88eabc29e20fa167ab093e6937b15a473570 Signed-off-by: Bernd Hufmann <bernd.hufmann@ericsson.com> Reviewed-on: https://git.eclipse.org/r/c/tracecompass.incubator/org.eclipse.tracecompass.incubator/+/199322 Tested-by: Marco Miller <marco.miller@ericsson.com> Tested-by: Trace Compass Bot <tracecompass-bot@eclipse.org> Reviewed-by: Marco Miller <marco.miller@ericsson.com> Reviewed-on: https://git.eclipse.org/r/c/tracecompass.incubator/org.eclipse.tracecompass.incubator/+/199426
diff --git a/trace-server/org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests/src/org/eclipse/tracecompass/incubator/trace/server/jersey/rest/core/tests/services/DataProviderServiceTest.java b/trace-server/org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests/src/org/eclipse/tracecompass/incubator/trace/server/jersey/rest/core/tests/services/DataProviderServiceTest.java index 2ac07b0..ca2faab 100644 --- a/trace-server/org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests/src/org/eclipse/tracecompass/incubator/trace/server/jersey/rest/core/tests/services/DataProviderServiceTest.java +++ b/trace-server/org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests/src/org/eclipse/tracecompass/incubator/trace/server/jersey/rest/core/tests/services/DataProviderServiceTest.java
@@ -39,8 +39,6 @@ import org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests.stubs.ColumnHeaderEntryStub; import org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests.stubs.DataProviderDescriptorStub; import org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests.stubs.EntryHeaderStub; -import org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests.stubs.EntryModelStub; -import org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests.stubs.EntryStub; import org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests.stubs.ExperimentModelStub; import org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests.stubs.LineModelStub; import org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests.stubs.TableColumnsOutputResponseStub; @@ -54,10 +52,12 @@ import org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests.stubs.TimeGraphModelStub; import org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests.stubs.TimeGraphRowStub; import org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests.stubs.TimeGraphStateStub; -import org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests.stubs.TreeOutputResponseStub; +import org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests.stubs.XyEntryModelStub; +import org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests.stubs.XyEntryStub; import org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests.stubs.XyModelStub; import org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests.stubs.XyOutputResponseStub; import org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests.stubs.XySeriesStub; +import org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests.stubs.XyTreeOutputResponseStub; import org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests.stubs.webapp.TestDataProviderService; import org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests.utils.RestServerTest; import org.eclipse.tracecompass.internal.tmf.core.model.filters.FetchParametersUtils; @@ -78,6 +78,7 @@ private static final int MAX_ITER = 40; private static final String CALL_STACK_DATAPROVIDER_ID = "org.eclipse.tracecompass.internal.analysis.profiling.callstack.provider.CallStackDataProvider"; private static final String XY_DATAPROVIDER_ID = "org.eclipse.tracecompass.analysis.os.linux.core.cpuusage.CpuUsageDataProvider"; + private static final String XY_HISTOGRAM_DATAPROVIDER_ID = "org.eclipse.tracecompass.internal.tmf.core.histogram.HistogramDataProvider"; private static final String EVENTS_TABLE_DATAPROVIDER_ID = "org.eclipse.tracecompass.internal.provisional.tmf.core.model.events.TmfEventTableDataProvider"; private static final String REQUESTED_TIMERANGE_KEY = "requested_timerange"; private static final String REQUESTED_TIMES_KEY = "requested_times"; @@ -157,10 +158,10 @@ Map<String, Object> parameters = new HashMap<>(); parameters.put(REQUESTED_TIMES_KEY, ImmutableList.of(start, end)); - TreeOutputResponseStub responseModel; + XyTreeOutputResponseStub responseModel; Response tree = xyTree.request().post(Entity.json(new QueryParameters(parameters, Collections.emptyList()))); assertEquals("There should be a positive response for the data provider", 200, tree.getStatus()); - responseModel = tree.readEntity(TreeOutputResponseStub.class); + responseModel = tree.readEntity(XyTreeOutputResponseStub.class); assertNotNull(responseModel); tree.close(); @@ -170,14 +171,14 @@ Thread.sleep(100); Response xyResponse = xyTree.request().post(Entity.json(new QueryParameters(parameters, Collections.emptyList()))); assertEquals("There should be a positive response for the data provider", 200, xyResponse.getStatus()); - responseModel = xyResponse.readEntity(TreeOutputResponseStub.class); + responseModel = xyResponse.readEntity(XyTreeOutputResponseStub.class); assertNotNull(responseModel); iteration++; xyResponse.close(); } // Verify tree model - EntryModelStub model = responseModel.getModel(); + XyEntryModelStub model = responseModel.getModel(); assertNotNull(model); List<EntryHeaderStub> headers = model.getHeaders(); assertNotNull(headers); @@ -190,13 +191,13 @@ } // Verify Entries assertNotNull("The model is null, maybe the analysis did not run long enough?" + responseModel, model); - List<EntryStub> entries = model.getEntries(); + List<XyEntryStub> entries = model.getEntries(); assertFalse(entries.isEmpty()); // Test getting the XY series endpoint WebTarget xySeriesEnpoint = getXYSeriesEndpoint(exp.getUUID().toString(), XY_DATAPROVIDER_ID); List<Integer> items = new ArrayList<>(); - for (EntryStub entry : entries) { + for (XyEntryStub entry : entries) { items.add(entry.getId()); } parameters.remove(REQUESTED_TIMES_KEY); @@ -221,6 +222,67 @@ } /** + * Verify that Histogram Data Provider fetchTree() interface and verify that + * the serialized fields are the expected ones according to the protocol. + * + * @throws InterruptedException + * Exception thrown while waiting to execute again + */ + @Test + public void testHistogramDataProvider() throws InterruptedException { + long start = 1412670961211260539L; + long end = 1412670967217750839L; + try { + ExperimentModelStub exp = assertPostExperiment(ARM_64_KERNEL_STUB.getName(), ARM_64_KERNEL_STUB); + + // Test getting the tree endpoint for an XY chart + WebTarget xyTree = getXYTreeEndpoint(exp.getUUID().toString(), XY_HISTOGRAM_DATAPROVIDER_ID); + + Map<String, Object> parameters = new HashMap<>(); + parameters.put(REQUESTED_TIMES_KEY, ImmutableList.of(start, end)); + XyTreeOutputResponseStub responseModel; + Response tree = xyTree.request().post(Entity.json(new QueryParameters(parameters, Collections.emptyList()))); + assertEquals("There should be a positive response for the data provider", 200, tree.getStatus()); + responseModel = tree.readEntity(XyTreeOutputResponseStub.class); + assertNotNull(responseModel); + tree.close(); + + // Make sure the analysis ran enough and we have a model + int iteration = 0; + while (responseModel.isRunning() && responseModel.getModel() == null && iteration < MAX_ITER) { + Thread.sleep(100); + Response xyResponse = xyTree.request().post(Entity.json(new QueryParameters(parameters, Collections.emptyList()))); + assertEquals("There should be a positive response for the data provider", 200, xyResponse.getStatus()); + responseModel = xyResponse.readEntity(XyTreeOutputResponseStub.class); + assertNotNull(responseModel); + iteration++; + xyResponse.close(); + } + + // Verify tree model + XyEntryModelStub model = responseModel.getModel(); + assertNotNull(model); + // Verify Entries + assertNotNull("The model is null, maybe the analysis did not run long enough?" + responseModel, model); + List<XyEntryStub> entries = model.getEntries(); + assertFalse(entries.isEmpty()); + + for (XyEntryStub entry : entries) { + if (entry.getParentId() == -1) { + assertFalse(entry.isDefault()); + } else { + assertTrue(entry.isDefault()); + } + } + } catch (ProcessingException e) { + // The failure from this exception alone is not helpful. Use the + // suppressed exception's message be the failure message for more + // help debugging failed tests. + fail(e.getCause().getMessage()); + } + } + + /** * Ensure that a time graph data provider exists and returns correct data. * It does not test the data itself, simply that the serialized fields are * the expected ones.
diff --git a/trace-server/org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests/src/org/eclipse/tracecompass/incubator/trace/server/jersey/rest/core/tests/stubs/XyEntryModelStub.java b/trace-server/org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests/src/org/eclipse/tracecompass/incubator/trace/server/jersey/rest/core/tests/stubs/XyEntryModelStub.java new file mode 100644 index 0000000..602d742 --- /dev/null +++ b/trace-server/org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests/src/org/eclipse/tracecompass/incubator/trace/server/jersey/rest/core/tests/stubs/XyEntryModelStub.java
@@ -0,0 +1,68 @@ +/********************************************************************** + * Copyright (c) 2023 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 + **********************************************************************/ +package org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests.stubs; + +import java.io.Serializable; +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * A Stub class for the entry model. It matches the trace server protocol's + * <code>XYEntryModel</code> schema + * + * @author Bernd Hufmann + */ +@JsonIgnoreProperties(ignoreUnknown = true) +public class XyEntryModelStub implements Serializable { + + private static final long serialVersionUID = -5846598539343152768L; + + private final List<XyEntryStub> fEntries; + private final List<EntryHeaderStub> fHeaders; + + /** + * {@link JsonCreator} Constructor for final fields + * + * @param entries + * The set of entries for this model + * @param headers + * The set of headers for this model + */ + @JsonCreator + public XyEntryModelStub(@JsonProperty("entries") List<XyEntryStub> entries, + @JsonProperty("headers") List<EntryHeaderStub> headers) { + fEntries = Objects.requireNonNull(entries, "The 'entries' json field was not set"); + fHeaders = headers == null ? Collections.emptyList() : headers; + } + + /** + * Get the entries described by this model + * + * @return The entries in this model + */ + public List<XyEntryStub> getEntries() { + return fEntries; + } + + /** + * Get the headers that describe this model + * + * @return The headers in this model + */ + public List<EntryHeaderStub> getHeaders() { + return fHeaders; + } +}
diff --git a/trace-server/org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests/src/org/eclipse/tracecompass/incubator/trace/server/jersey/rest/core/tests/stubs/XyEntryStub.java b/trace-server/org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests/src/org/eclipse/tracecompass/incubator/trace/server/jersey/rest/core/tests/stubs/XyEntryStub.java new file mode 100644 index 0000000..8eff2f3 --- /dev/null +++ b/trace-server/org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests/src/org/eclipse/tracecompass/incubator/trace/server/jersey/rest/core/tests/stubs/XyEntryStub.java
@@ -0,0 +1,64 @@ +/********************************************************************** + * Copyright (c) 2023 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 + **********************************************************************/ +package org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests.stubs; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * A Stub class for the entry elements. It matches the trace server protocol's + * <code>XY Entry</code> schema + * + * @author Bernd Hufmann + */ +public class XyEntryStub extends EntryStub { + + private static final long serialVersionUID = 8369475974133990978L; + + private final boolean fIsDefault; + + /** + * {@link JsonCreator} Constructor for final fields + * + * @param labels + * The labels of this entry + * @param id + * The unique ID of the entry + * @param parentId + * The unique id of the parent of this entry + * @param hasRowModel + * Whether this entry has data + * @param style + * The style of this entry + * @param isDefault + * whether the entry is a default entry (default selection) + */ + @JsonCreator + public XyEntryStub(@JsonProperty("labels") List<String> labels, + @JsonProperty("id") Integer id, + @JsonProperty("parentId") Integer parentId, + @JsonProperty("hasData") boolean hasRowModel, + @JsonProperty("style") OutputElementStyleStub style, + @JsonProperty("isDefault") boolean isDefault) { + super(labels, id, parentId, hasRowModel, style); + fIsDefault = isDefault; + } + + /** + * @return whether the entry is a default entry and should be selected by + * default + */ + public boolean isDefault() { + return fIsDefault; + } +}
diff --git a/trace-server/org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests/src/org/eclipse/tracecompass/incubator/trace/server/jersey/rest/core/tests/stubs/XyTreeOutputResponseStub.java b/trace-server/org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests/src/org/eclipse/tracecompass/incubator/trace/server/jersey/rest/core/tests/stubs/XyTreeOutputResponseStub.java new file mode 100644 index 0000000..7e66549 --- /dev/null +++ b/trace-server/org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests/src/org/eclipse/tracecompass/incubator/trace/server/jersey/rest/core/tests/stubs/XyTreeOutputResponseStub.java
@@ -0,0 +1,52 @@ +/********************************************************************** + * Copyright (c) 2023 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 + **********************************************************************/ +package org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests.stubs; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * A stub class for the response to a tree request for xy charts and data trees. + * It contains the generic response, as well as an {@link XyEntryModelStub} + * + * @author Bernd Hufmann + */ +public class XyTreeOutputResponseStub extends OutputResponseStub { + + private static final long serialVersionUID = -4155622509432733184L; + private final XyEntryModelStub fModel; + + /** + * {@link JsonCreator} Constructor from json + * + * @param model + * The model for this response + * @param status + * The status of the response + * @param statusMessage + * The custom status message of the response + */ + public XyTreeOutputResponseStub(@JsonProperty("model") XyEntryModelStub model, + @JsonProperty("status") String status, + @JsonProperty("statusMessage") String statusMessage) { + super(status, statusMessage); + fModel = model; + } + + /** + * Get the model for this response + * + * @return The model for the response + */ + public XyEntryModelStub getModel() { + return fModel; + } +}
diff --git a/trace-server/org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core/src/org/eclipse/tracecompass/incubator/internal/trace/server/jersey/rest/core/webapp/TmfTreeModelSerializer.java b/trace-server/org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core/src/org/eclipse/tracecompass/incubator/internal/trace/server/jersey/rest/core/webapp/TmfTreeModelSerializer.java index dbd0ff2..e826936 100644 --- a/trace-server/org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core/src/org/eclipse/tracecompass/incubator/internal/trace/server/jersey/rest/core/webapp/TmfTreeModelSerializer.java +++ b/trace-server/org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core/src/org/eclipse/tracecompass/incubator/internal/trace/server/jersey/rest/core/webapp/TmfTreeModelSerializer.java
@@ -15,6 +15,7 @@ import org.eclipse.jdt.annotation.NonNull; import org.eclipse.tracecompass.tmf.core.model.tree.TmfTreeDataModel; +import org.eclipse.tracecompass.tmf.core.model.xy.ITmfXyEntryModel; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.SerializerProvider; @@ -51,7 +52,11 @@ } gen.writeEndArray(); gen.writeBooleanField("hasData", value.hasRowModel()); //$NON-NLS-1$ + + if (value instanceof ITmfXyEntryModel) { + ITmfXyEntryModel xyValue = (ITmfXyEntryModel) value; + gen.writeBooleanField("isDefault", xyValue.isDefault()); //$NON-NLS-1$ + } gen.writeEndObject(); } - }