Skip to content

Commit

Permalink
server.tests: Add tests for querying marker sets and annotations
Browse files Browse the repository at this point in the history
Signed-off-by: Bernd Hufmann <[email protected]>
  • Loading branch information
bhufmann committed Dec 18, 2024
1 parent bf927d5 commit 8379bc5
Show file tree
Hide file tree
Showing 12 changed files with 744 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<marker-sets xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="markers.xsd">
<marker-set name="Example" id="example.id">
<marker name="Frame" color="#ff0000" period="10" unit="ms" range="0..4095">
<submarker name="Subframe" color="#00ff00" label="#%d Normal" range="0..9" index="0,2..9">
<submarker name="Slot" color="#008800" range="0..1"/>
</submarker>
<submarker name="Subframe" color="#ff8800" label="#%d Special" range="0..9" index="1">
<segments name="Slot">
<segment label="A" color="#884400" length="1"/>
<segment label="B" color="#884400" length="3"/>
<segment label="C" color="#884400" length="2"/>
</segments>
</submarker>
</marker>
</marker-set>
</marker-sets>
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,10 @@
id="org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests.stubs.TestDataProviderFactory">
</dataProviderFactory>
</extension>
<extension
point="org.eclipse.tracecompass.tmf.core.custom.marker">
<customMarker
file="config/markers.xml">
</customMarker>
</extension>
</plugin>
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@
package org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests.services;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import java.util.List;
import java.util.Set;

import javax.ws.rs.client.WebTarget;
Expand All @@ -23,6 +25,8 @@
import org.eclipse.tracecompass.incubator.internal.trace.server.jersey.rest.core.services.DataProviderService;
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.ExperimentModelStub;
import org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests.stubs.MarkerSetStub;
import org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests.stubs.MarkerSetsOutputResponseStub;
import org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests.utils.RestServerTest;
import org.junit.Test;

Expand Down Expand Up @@ -69,4 +73,22 @@ public void testProvider() {

assertEquals(EXPECTED_CALLSTACK_PROVIDER_DESCRIPTOR, descriptor);
}

/**
* Test of getting marker sets
*
* Note: For this test a marker set extension is defined in the plugin.xml
* of this test plug-in.
*/
@Test
public void testGetMarkerSets() {
ExperimentModelStub exp = assertPostExperiment(sfContextSwitchesUstNotInitializedStub.getName(), sfContextSwitchesUstNotInitializedStub);

MarkerSetsOutputResponseStub outputResponseStub = getMarkerSetsEndpoint(exp.getUUID().toString()).request(MediaType.APPLICATION_JSON).get(MarkerSetsOutputResponseStub.class);
assertNotNull(outputResponseStub);
List<MarkerSetStub> markerSets = outputResponseStub.getModel();
assertFalse(markerSets.isEmpty());
assertEquals("Example", markerSets.get(0).getName());
assertEquals("example.id", markerSets.get(0).getId());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import javax.ws.rs.ProcessingException;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;

Expand All @@ -41,6 +42,10 @@
import org.eclipse.tracecompass.incubator.internal.trace.server.jersey.rest.core.model.views.QueryParameters;
import org.eclipse.tracecompass.incubator.internal.trace.server.jersey.rest.core.services.DataProviderService;
import org.eclipse.tracecompass.incubator.internal.trace.server.jersey.rest.core.services.EndpointConstants;
import org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests.stubs.AnnotationCategoriesOutputResponseStub;
import org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests.stubs.AnnotationModelStub;
import org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests.stubs.AnnotationResponseStub;
import org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests.stubs.AnnotationStub;
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.OutputElementStyleStub;
import org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests.stubs.OutputStyleModelStub;
Expand All @@ -58,6 +63,7 @@
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;
import org.eclipse.tracecompass.tmf.core.model.annotations.IAnnotation.AnnotationType;
import org.eclipse.tracecompass.tmf.core.model.filters.TimeQueryFilter;
import org.junit.Test;

Expand All @@ -74,11 +80,16 @@
@SuppressWarnings({"null", "restriction"})
public class TimeGraphDataProviderServiceTest extends RestServerTest {

private static final String UST_CATEGORY_NAME = "ust";
private static final String SLOT_CATEGORY_NAME = "Slot";
private static final String CTX_SWITCH_EXPERIMENT = "ctxSwitchExperiment";
private static final String THREAD_STATUS_DP_ID = "org.eclipse.tracecompass.internal.analysis.os.linux.core.threadstatus.ThreadStatusDataProvider";
private static final String DATA_PROVIDER_RESPONSE_FAILED_MSG = "There should be a positive response for the data provider";
private static final String MODEL_NULL_MSG = "The model is null, maybe the analysis did not run long enough?";
private static final int MAX_ITER = 40;
private static final String REQUESTED_TIMERANGE_KEY = "requested_timerange";
private static final String REQUESTED_CATAGORIES_KEY = "requested_marker_categories";
private static final String REQUESTED_MARKERSET_ID_KEY = "requested_marker_set";
private static final String REQUESTED_ITEMS_KEY = "requested_items";
private static final String REQUESTED_ELEMENT_KEY = "requested_element";
private static final String ELEMENT_TYPE = "elementType";
Expand Down Expand Up @@ -209,6 +220,140 @@ public void testArrowsErrors() {
executePostErrorTests(exp, RestServerTest::getArrowsEndpoint, THREAD_STATUS_DP_ID, true);
}

/**
* Tests querying annotation categories for a time graph data provider
*/
@Test
public void testAnnotationCategories() {
ExperimentModelStub exp = assertPostExperiment(CTX_SWITCH_EXPERIMENT, sfContextSwitchesKernelNotInitializedStub, sfContextSwitchesUstNotInitializedStub);

// Get ust category
WebTarget categoriesEndpoint = getAnnotationCategoriesEndpoint(exp.getUUID().toString(), THREAD_STATUS_DP_ID, "unknown.annotation.cat.id");
AnnotationCategoriesOutputResponseStub annotationCategoriesModel = categoriesEndpoint.request(MediaType.APPLICATION_JSON).get(AnnotationCategoriesOutputResponseStub.class);
assertNotNull(annotationCategoriesModel);
assertFalse(annotationCategoriesModel.getModel().getAnnotationCategories().isEmpty());
List<String> categories = annotationCategoriesModel.getModel().getAnnotationCategories();
assertFalse(categories.isEmpty());
assertTrue(categories.contains(UST_CATEGORY_NAME));

// get category from marker set
categoriesEndpoint = getAnnotationCategoriesEndpoint(exp.getUUID().toString(), THREAD_STATUS_DP_ID, "example.id");
annotationCategoriesModel = categoriesEndpoint.request(MediaType.APPLICATION_JSON).get(AnnotationCategoriesOutputResponseStub.class);

assertNotNull(annotationCategoriesModel);
categories = annotationCategoriesModel.getModel().getAnnotationCategories();
assertFalse(categories.isEmpty());
List<String> expectedCategories = List.of("Frame", "Subframe", SLOT_CATEGORY_NAME);
assertTrue(categories.containsAll(expectedCategories));
}

/**
* Tests error cases when querying annotation categories for a time graph data provider
*/
@Test
public void testAnnotationCategoriesErrors() {
ExperimentModelStub exp = assertPostExperiment(sfContextSwitchesKernelNotInitializedStub.getName(), sfContextSwitchesKernelNotInitializedStub);
// Invalid UUID string
WebTarget endpoint = getAnnotationCategoriesEndpoint(INVALID_EXP_UUID, THREAD_STATUS_DP_ID);
try (Response response = endpoint.request(MediaType.APPLICATION_JSON).get()) {
assertNotNull(response);
assertEquals(Status.NOT_FOUND.getStatusCode(), response.getStatus());
}

// Unknown experiment
endpoint = getAnnotationCategoriesEndpoint(UUID.randomUUID().toString(), THREAD_STATUS_DP_ID);
try (Response response = endpoint.request(MediaType.APPLICATION_JSON).get()) {
assertNotNull(response);
assertEquals(Status.NOT_FOUND.getStatusCode(), response.getStatus());
assertEquals(EndpointConstants.NO_SUCH_TRACE, response.readEntity(String.class));
}

// Unknown data provider
endpoint = getAnnotationCategoriesEndpoint(exp.getUUID().toString(), UNKNOWN_DP_ID);
try (Response response = endpoint.request(MediaType.APPLICATION_JSON).get()) {
assertNotNull(response);
assertEquals(Status.METHOD_NOT_ALLOWED.getStatusCode(), response.getStatus());
assertEquals(EndpointConstants.NO_PROVIDER, response.readEntity(String.class));
}
}

/**
* Tests querying annotation for a time graph data provider
*
* @throws InterruptedException
* if such exception occurred
*/
@Test
public void testAnnotations() throws InterruptedException {
ExperimentModelStub exp = assertPostExperiment(CTX_SWITCH_EXPERIMENT, sfContextSwitchesKernelNotInitializedStub, sfContextSwitchesUstNotInitializedStub);
Set<TimeGraphEntryStub> entries = loadDataProvider(exp, THREAD_STATUS_DP_ID);

Map<String, Object> parameters = new HashMap<>();
parameters.remove(REQUESTED_TIMES_KEY);
parameters.put(REQUESTED_TIMERANGE_KEY, ImmutableMap.of(START, 1450193722866679365L, END, 1450193722881450790L, NB_TIMES, 500));
parameters.put(REQUESTED_MARKERSET_ID_KEY, "example.id");
List<String> categories = List.of("Frame", "Subframe", SLOT_CATEGORY_NAME, UST_CATEGORY_NAME);
parameters.put(REQUESTED_CATAGORIES_KEY, categories);

// Find specific thread entry
final String threadNameForTooltip = "lemon_server";
Optional<TimeGraphEntryStub> threadOptional = entries.stream().filter(
entry -> threadNameForTooltip.equals(entry.getLabels().get(0)) && entry.getLabels().get(1).equals("592")).findFirst();
assertTrue(threadOptional.isPresent());
parameters.put(REQUESTED_ITEMS_KEY, List.of(threadOptional.get().getId()));

WebTarget annoationEndpoint = getAnnotationEndpoint(exp.getUUID().toString(), THREAD_STATUS_DP_ID);
try (Response response = annoationEndpoint.request().post(Entity.json(new QueryParameters(parameters, Collections.emptyList())))) {
assertNotNull(response);
assertEquals(Status.OK.getStatusCode(), response.getStatus());
AnnotationResponseStub modelResponse = response.readEntity(AnnotationResponseStub.class);
assertNotNull(modelResponse);

AnnotationModelStub annotationModel = modelResponse.getModel();
assertNotNull(annotationModel);
Map<String, Collection<AnnotationStub>> annotationsMap = annotationModel.getAnnotations();
assertFalse(annotationsMap.isEmpty());
for (String category : categories) {
assertTrue(annotationsMap.containsKey(category));
Collection<AnnotationStub> annotations = annotationsMap.get(category);
assertNotNull(annotations);
assertFalse(annotations.isEmpty());
}

Collection<AnnotationStub> annotations = annotationsMap.get(SLOT_CATEGORY_NAME);
assertNotNull(annotations);
AnnotationStub annotation = annotations.iterator().next();

// Verify first annotation created from marker set and category Slot
assertEquals(1450193722866500000L, annotation.getTime());
assertEquals(500000, annotation.getDuration());
assertEquals(-1, annotation.getEntryId());
assertEquals("1", annotation.getLabel());
assertEquals(AnnotationType.CHART.name(), annotation.getType());
assertNotNull(annotation.getStyle());

// Verify first annotation created from category ust for specific thread
annotations = annotationsMap.get(UST_CATEGORY_NAME);
assertNotNull(annotations);
annotation = annotations.iterator().next();
assertEquals(1450193722867264709L, annotation.getTime());
assertEquals(0, annotation.getDuration());
assertEquals(threadOptional.get().getId(), annotation.getEntryId());
assertEquals("lttng_ust_tracef:event", annotation.getLabel());
assertEquals(AnnotationType.CHART.name(), annotation.getType());
assertNotNull(annotation.getStyle());
}
}

/**
* Tests error cases when querying annotation for a time graph data provider
*/
@Test
public void testAnnotationErrors() {
ExperimentModelStub exp = assertPostExperiment(sfContextSwitchesKernelNotInitializedStub.getName(), sfContextSwitchesKernelNotInitializedStub);
executePostErrorTests(exp, RestServerTest::getAnnotationEndpoint, THREAD_STATUS_DP_ID, true);
}

private static void testGetStates(String filterStrategy) throws InterruptedException {
try {
ExperimentModelStub exp = assertPostExperiment(sfContextSwitchesUstNotInitializedStub.getName(), sfContextSwitchesUstNotInitializedStub);
Expand Down Expand Up @@ -503,5 +648,4 @@ private static void executePostErrorTests (ExperimentModelStub exp, IEndpointRes
assertEquals(EndpointConstants.NO_PROVIDER, response.readEntity(String.class));
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**********************************************************************
* Copyright (c) 2024 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.List;

import com.fasterxml.jackson.annotation.JsonProperty;

/**
* Basic Implementation of the serialized annotation category used by clients.
*
* @author Bernd Hufmann
*/
public class AnnotationCategoriesModelStub implements Serializable{

private static final long serialVersionUID = -7146696718088222398L;
private final List<String> fAnnotationCategories;

/**
* Constructor
*
* @param annotationCategories
* List of categories
*/
public AnnotationCategoriesModelStub(@JsonProperty("annotationCategories") List<String> annotationCategories) {
fAnnotationCategories = annotationCategories;
}

/**
* Annotation categories for the model
*
* @return List of categories
*/
public List<String> getAnnotationCategories() {
return fAnnotationCategories;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/**********************************************************************
* Copyright (c) 2024 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 Annotation Categories' request. It contains
* the generic response, as well as an lsit of {@link AnnotationCategoriesModelStub}
*
* @author Bernd Hufmann
*/
public class AnnotationCategoriesOutputResponseStub extends OutputResponseStub {

private static final long serialVersionUID = -2547573713331714274L;
private final AnnotationCategoriesModelStub 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 AnnotationCategoriesOutputResponseStub(@JsonProperty("model") AnnotationCategoriesModelStub 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 AnnotationCategoriesModelStub getModel() {
return fModel;
}

}
Loading

0 comments on commit 8379bc5

Please sign in to comment.