| /******************************************************************************* |
| * Copyright (c) 2018, 2021 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.utils; |
| |
| import static org.junit.Assert.assertEquals; |
| |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import javax.ws.rs.client.Client; |
| import javax.ws.rs.client.ClientBuilder; |
| import javax.ws.rs.client.Entity; |
| import javax.ws.rs.client.WebTarget; |
| import javax.ws.rs.core.GenericType; |
| import javax.ws.rs.core.MediaType; |
| import javax.ws.rs.core.Response; |
| |
| import org.eclipse.core.runtime.FileLocator; |
| 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.webapp.TraceServerConfiguration; |
| import org.eclipse.tracecompass.incubator.internal.trace.server.jersey.rest.core.webapp.WebApplication; |
| 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.TraceModelStub; |
| import org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests.stubs.webapp.TestWebApplication; |
| import org.eclipse.tracecompass.testtraces.ctf.CtfTestTrace; |
| import org.eclipse.tracecompass.tmf.core.dataprovider.IDataProviderDescriptor.ProviderType; |
| import org.junit.After; |
| import org.junit.Before; |
| import org.junit.BeforeClass; |
| |
| import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider; |
| import com.google.common.collect.ImmutableList; |
| |
| /** |
| * Rest server test abstract class, handles starting the server in test mode, |
| * getting the correct client, and closing the traces and server once the test |
| * is complete |
| * |
| * @author Loic Prieur-Drevon |
| */ |
| public abstract class RestServerTest { |
| private static final String SERVER = "http://localhost:8378/tsp/api"; //$NON-NLS-1$ |
| private static final WebApplication fWebApp = new TestWebApplication(new TraceServerConfiguration(TraceServerConfiguration.TEST_PORT, false, null, null)); |
| /** |
| * Traces endpoint path (relative to application). |
| */ |
| public static final String TRACES = "traces"; |
| /** |
| * Experiments endpoint path (relative to application). |
| */ |
| public static final String EXPERIMENTS = "experiments"; |
| |
| /** |
| * Outputs path segment |
| */ |
| public static final String OUTPUTS_PATH = "outputs"; |
| |
| /** |
| * Tree path segment |
| */ |
| public static final String TREE_PATH = "tree"; |
| |
| /** |
| * Data Tree path segment |
| */ |
| public static final String DATATREE_PATH = "data"; |
| |
| /** |
| * Time Graph path segment |
| */ |
| public static final String TIMEGRAPH_PATH = "timeGraph"; |
| |
| /** |
| * XY path segment |
| */ |
| public static final String XY_PATH = "XY"; |
| |
| /** |
| * XY series path segment |
| */ |
| public static final String XY_SERIES_PATH = "xy"; |
| |
| /** |
| * States path segment |
| */ |
| public static final String STATE_PATH = "states"; |
| |
| /** |
| * Tooltip path segment |
| */ |
| public static final String TOOLTIP_PATH = "tooltip"; |
| |
| /** |
| * Table path segment |
| */ |
| public static final String TABLE_PATH = "table"; |
| |
| /** |
| * Column path segment |
| */ |
| public static final String TABLE_COLUMN_PATH = "columns"; |
| |
| /** |
| * Lines path segment |
| */ |
| public static final String TABLE_LINE_PATH = "lines"; |
| |
| /** |
| * <b>name</b> constant |
| */ |
| public static final String NAME = "name"; |
| /** |
| * <b>path</b> constant |
| */ |
| public static final String URI = "uri"; |
| |
| /** |
| * Configuration service root path |
| */ |
| public static final String CONFIG_PATH = "config"; |
| |
| /** |
| * Configuration types path segment |
| */ |
| public static final String TYPES_PATH = "types"; |
| |
| /** |
| * Configuration instances path segment |
| */ |
| public static final String CONFIG_INSTANCES_PATH = "configs"; |
| |
| private static final GenericType<Set<TraceModelStub>> TRACE_MODEL_SET_TYPE = new GenericType<Set<TraceModelStub>>() { |
| }; |
| private static final GenericType<Set<ExperimentModelStub>> EXPERIMENT_MODEL_SET_TYPE = new GenericType<Set<ExperimentModelStub>>() { |
| }; |
| private static final GenericType<Set<DataProviderDescriptorStub>> DATAPROVIDER_DESCR_MODEL_SET_TYPE = new GenericType<Set<DataProviderDescriptorStub>>() { |
| }; |
| |
| /** |
| * {@link TraceModelStub} to represent the object returned by the server for |
| * {@link CtfTestTrace#CONTEXT_SWITCHES_UST}. |
| */ |
| protected static TraceModelStub CONTEXT_SWITCHES_UST_STUB; |
| |
| /** |
| * The name used when posting the trace. |
| */ |
| protected static final String CONTEXT_SWITCHES_UST_NAME = "ust"; |
| |
| /** |
| * {@link TraceModelStub} to represent the object returned by the server for |
| * {@link CtfTestTrace#CONTEXT_SWITCHES_KERNEL}. |
| */ |
| protected static TraceModelStub CONTEXT_SWITCHES_KERNEL_STUB; |
| |
| /** |
| * The name used when posting the trace. |
| */ |
| protected static final String CONTEXT_SWITCHES_KERNEL_NAME = "kernel"; |
| |
| /** |
| * {@link TraceModelStub} to represent the object returned by the server for |
| * {@link CtfTestTrace#ARM_64_BIT_HEADER}, with the same name as {@link #CONTEXT_SWITCHES_KERNEL_STUB} |
| */ |
| protected static TraceModelStub ARM_64_KERNEL_STUB; |
| |
| /** |
| * The name used when posting the trace. |
| */ |
| protected static final String ARM_64_KERNEL_NAME = "kernel"; |
| |
| /** |
| * Expected toString() of all data providers for this experiment |
| */ |
| protected static List<DataProviderDescriptorStub> EXPECTED_DATA_PROVIDER_DESCRIPTOR = null; |
| |
| /** |
| * Create the {@link TraceModelStub}s before running the tests |
| * |
| * @throws IOException |
| * if the URL could not be converted to a path |
| */ |
| @BeforeClass |
| public static void beforeTest() throws IOException { |
| String contextSwitchesUstPath = FileLocator.toFileURL(CtfTestTrace.CONTEXT_SWITCHES_UST.getTraceURL()).getPath().replaceAll("/$", ""); |
| CONTEXT_SWITCHES_UST_STUB = new TraceModelStub(CONTEXT_SWITCHES_UST_NAME, contextSwitchesUstPath); |
| |
| String contextSwitchesKernelPath = FileLocator.toFileURL(CtfTestTrace.CONTEXT_SWITCHES_KERNEL.getTraceURL()).getPath().replaceAll("/$", ""); |
| CONTEXT_SWITCHES_KERNEL_STUB = new TraceModelStub(CONTEXT_SWITCHES_KERNEL_NAME, contextSwitchesKernelPath); |
| |
| String arm64Path = FileLocator.toFileURL(CtfTestTrace.ARM_64_BIT_HEADER.getTraceURL()).getPath().replaceAll("/$", ""); |
| ARM_64_KERNEL_STUB = new TraceModelStub(ARM_64_KERNEL_NAME, arm64Path); |
| |
| ImmutableList.Builder<DataProviderDescriptorStub> b = ImmutableList.builder(); |
| b.add(new DataProviderDescriptorStub("org.eclipse.tracecompass.internal.analysis.timing.core.segmentstore.scatter.dataprovider:org.eclipse.linuxtools.lttng2.ust.analysis.callstack", |
| "LTTng-UST CallStack - Latency vs Time", |
| "Show latencies provided by Analysis module: LTTng-UST CallStack", |
| ProviderType.TREE_TIME_XY.name())); |
| b.add(new DataProviderDescriptorStub("org.eclipse.tracecompass.internal.analysis.profiling.callstack.provider.CallStackDataProvider", |
| "Flame Chart", |
| "Show a call stack over time", |
| ProviderType.TIME_GRAPH.name())); |
| b.add(new DataProviderDescriptorStub("org.eclipse.tracecompass.internal.tmf.core.histogram.HistogramDataProvider", |
| "Histogram", |
| "Show a histogram of number of events to time for a trace", |
| ProviderType.TREE_TIME_XY.name())); |
| EXPECTED_DATA_PROVIDER_DESCRIPTOR = b.build(); |
| } |
| |
| /** |
| * Start the Eclipse / Jetty Web server |
| * |
| * @throws Exception |
| * if there is a problem running this application. |
| */ |
| @Before |
| public void startServer() throws Exception { |
| fWebApp.start(); |
| } |
| |
| /** |
| * Stop the server once tests are finished, and close the traces |
| */ |
| @After |
| public void stopServer() { |
| WebTarget application = getApplicationEndpoint(); |
| WebTarget experimentsTarget = application.path(EXPERIMENTS); |
| for (ExperimentModelStub experiment: getExperiments(experimentsTarget)) { |
| assertEquals(experiment, experimentsTarget.path(experiment.getUUID().toString()).request().delete().readEntity(ExperimentModelStub.class)); |
| } |
| WebTarget traceTarget = application.path(TRACES); |
| for (TraceModelStub trace : getTraces(traceTarget)) { |
| assertEquals(trace, traceTarget.path(trace.getUUID().toString()).request().delete().readEntity(TraceModelStub.class)); |
| } |
| assertEquals(Collections.emptySet(), getTraces(traceTarget)); |
| assertEquals(Collections.emptySet(), getExperiments(experimentsTarget)); |
| fWebApp.stop(); |
| } |
| |
| /** |
| * Getter for the {@link WebTarget} for the application endpoint. |
| * |
| * @return the application endpoint {@link WebTarget}. |
| */ |
| public static WebTarget getApplicationEndpoint() { |
| Client client = ClientBuilder.newClient(); |
| client.register(JacksonJsonProvider.class); |
| return client.target(SERVER); |
| } |
| |
| /** |
| * Get the {@link WebTarget} for the table columns endpoint. |
| * |
| * @param expUUID |
| * Experiment UUID |
| * @param dataProviderId |
| * Data provider ID |
| * @return The time graph tree endpoint |
| */ |
| public static WebTarget getTableColumnsEndpoint(String expUUID, String dataProviderId) { |
| return getApplicationEndpoint().path(EXPERIMENTS) |
| .path(expUUID) |
| .path(OUTPUTS_PATH) |
| .path(TABLE_PATH) |
| .path(dataProviderId) |
| .path(TABLE_COLUMN_PATH); |
| } |
| |
| /** |
| * Get the {@link WebTarget} for the table lines endpoint. |
| * |
| * @param expUUID |
| * Experiment UUID |
| * @param dataProviderId |
| * Data provider ID |
| * @return The time graph tree endpoint |
| */ |
| public static WebTarget getTableLinesEndpoint(String expUUID, String dataProviderId) { |
| return getApplicationEndpoint().path(EXPERIMENTS) |
| .path(expUUID) |
| .path(OUTPUTS_PATH) |
| .path(TABLE_PATH) |
| .path(dataProviderId) |
| .path(TABLE_LINE_PATH); |
| } |
| |
| |
| /** |
| * Get the {@link WebTarget} for the data-tree tree endpoint. |
| * |
| * @param expUUID |
| * Experiment UUID |
| * @param dataProviderId |
| * Data provider ID |
| * @return The time graph tree endpoint |
| */ |
| public static WebTarget getDataTreeEndpoint(String expUUID, String dataProviderId) { |
| return getApplicationEndpoint().path(EXPERIMENTS) |
| .path(expUUID) |
| .path(OUTPUTS_PATH) |
| .path(DATATREE_PATH) |
| .path(dataProviderId) |
| .path(TREE_PATH); |
| } |
| |
| /** |
| * Get the {@link WebTarget} for the time graph tree endpoint. |
| * |
| * @param expUUID |
| * Experiment UUID |
| * @param dataProviderId |
| * Data provider ID |
| * @return The time graph tree endpoint |
| */ |
| public static WebTarget getTimeGraphTreeEndpoint(String expUUID, String dataProviderId) { |
| return getApplicationEndpoint().path(EXPERIMENTS) |
| .path(expUUID) |
| .path(OUTPUTS_PATH) |
| .path(TIMEGRAPH_PATH) |
| .path(dataProviderId) |
| .path(TREE_PATH); |
| } |
| |
| /** |
| * Get the {@link WebTarget} for the time graph state endpoint. |
| * |
| * @param expUUID |
| * Experiment UUID |
| * @param dataProviderId |
| * Data provider ID |
| * @return The time graph state endpoint |
| */ |
| public static WebTarget getTimeGraphStatesEndpoint(String expUUID, String dataProviderId) { |
| return getApplicationEndpoint().path(EXPERIMENTS) |
| .path(expUUID) |
| .path(OUTPUTS_PATH) |
| .path(TIMEGRAPH_PATH) |
| .path(dataProviderId) |
| .path(STATE_PATH); |
| } |
| |
| /** |
| * Get the {@link WebTarget} for the time graph tooltip endpoint. |
| * |
| * @param expUUID |
| * Experiment UUID |
| * @param dataProviderId |
| * Data provider ID |
| * @return The time graph tooltip endpoint |
| */ |
| public static WebTarget getTimeGraphTooltipEndpoint(String expUUID, String dataProviderId) { |
| return getApplicationEndpoint().path(EXPERIMENTS) |
| .path(expUUID) |
| .path(OUTPUTS_PATH) |
| .path(TIMEGRAPH_PATH) |
| .path(dataProviderId) |
| .path(TOOLTIP_PATH); |
| } |
| |
| /** |
| * Get the {@link WebTarget} for the XY tree endpoint. |
| * |
| * @param expUUID |
| * Experiment UUID |
| * @param dataProviderId |
| * Data provider ID |
| * @return The XY tree endpoint |
| */ |
| public static WebTarget getXYTreeEndpoint(String expUUID, String dataProviderId) { |
| return getApplicationEndpoint().path(EXPERIMENTS) |
| .path(expUUID) |
| .path(OUTPUTS_PATH) |
| .path(XY_PATH) |
| .path(dataProviderId) |
| .path(TREE_PATH); |
| } |
| |
| /** |
| * Get the {@link WebTarget} for the XY series endpoint. |
| * |
| * @param expUUID |
| * Experiment UUID |
| * @param dataProviderId |
| * Data provider ID |
| * @return The XY series endpoint |
| */ |
| public static WebTarget getXYSeriesEndpoint(String expUUID, String dataProviderId) { |
| return getApplicationEndpoint().path(EXPERIMENTS) |
| .path(expUUID) |
| .path(OUTPUTS_PATH) |
| .path(XY_PATH) |
| .path(dataProviderId) |
| .path(XY_SERIES_PATH); |
| } |
| |
| /** |
| * Get the traces currently open on the server. |
| * |
| * @param traces |
| * traces endpoint on the server |
| * @return list of currently open traces. |
| */ |
| public static Set<TraceModelStub> getTraces(WebTarget traces) { |
| return traces.request(MediaType.APPLICATION_JSON).get(TRACE_MODEL_SET_TYPE); |
| } |
| |
| /** |
| * Get the experiments currently open on the server. |
| * |
| * @param experiments |
| * experiment endpoint on the server. |
| * @return list of currently open experiments. |
| */ |
| public static Set<ExperimentModelStub> getExperiments(WebTarget experiments) { |
| return experiments.request(MediaType.APPLICATION_JSON).get(EXPERIMENT_MODEL_SET_TYPE); |
| } |
| |
| /** |
| * Get a set of {@link DataProviderDescriptorStub} |
| * |
| * @param outputs |
| * {@link WebTarget} for the outputs endpoint |
| * @return Set of {@link DataProviderDescriptorStub} given by the server |
| */ |
| public static Set<DataProviderDescriptorStub> getDataProviderDescriptors(WebTarget outputs) { |
| return outputs.request(MediaType.APPLICATION_JSON).get(DATAPROVIDER_DESCR_MODEL_SET_TYPE); |
| } |
| |
| /** |
| * Post the trace from an expected {@link TraceModelStub}, ensure that the post |
| * returned correctly and that the returned model was that of the expected stub. |
| * |
| * @param traces |
| * traces endpoint |
| * @param stub |
| * expected trace stub |
| * @return the resulting stub |
| */ |
| public static TraceModelStub assertPost(WebTarget traces, TraceModelStub stub) { |
| Map<String, Object> parameters = new HashMap<>(); |
| parameters.put(NAME, stub.getName()); |
| parameters.put(URI, stub.getPath()); |
| Response response = traces.request().post(Entity.json(new QueryParameters(parameters , Collections.emptyList()))); |
| int code = response.getStatus(); |
| assertEquals("Failed to POST " + stub.getName() + ", error code=" + code, 200, code); |
| TraceModelStub result = response.readEntity(TraceModelStub.class); |
| assertEquals(stub, result); |
| return result; |
| } |
| |
| /** |
| * Post an experiment from a list of {@link TraceModelStub}, ensure that the |
| * post returned correctly and that the returned model was that of the |
| * expected stub. |
| * |
| * @param name |
| * experiment name |
| * @param traces |
| * traces to include in experiment |
| * @return the resulting experiment stub |
| */ |
| public static ExperimentModelStub assertPostExperiment(String name, TraceModelStub... traces) { |
| WebTarget application = getApplicationEndpoint(); |
| List<String> traceUUIDs = new ArrayList<>(); |
| for (TraceModelStub trace : traces) { |
| TraceModelStub traceStub = assertPost(application.path(TRACES), trace); |
| traceUUIDs.add(traceStub.getUUID().toString()); |
| } |
| Map<String, Object> parameters = new HashMap<>(); |
| parameters.put(NAME, name); |
| parameters.put(TRACES, traceUUIDs); |
| Response response = application.path(EXPERIMENTS).request().post(Entity.json(new QueryParameters(parameters, Collections.emptyList()))); |
| assertEquals("Failed to POST experiment " + name + ", error code=" + response.getStatus(), 200, response.getStatus()); |
| return response.readEntity(ExperimentModelStub.class); |
| } |
| } |