From 08790ce62369a2c3c5e79963f0ea31bf91e11218 Mon Sep 17 00:00:00 2001 From: Bernd Hufmann Date: Tue, 22 Oct 2024 16:46:10 -0400 Subject: [PATCH] server: Add unit tests for configurable data providers Signed-off-by: Bernd Hufmann --- .../plugin.xml | 7 + .../ConfigurationManagerServiceTest.java | 20 +- .../services/DataProviderServiceTest.java | 266 ++++++++++++++++++ .../stubs/DataProviderDescriptorStub.java | 46 ++- .../tests/stubs/TestDataProviderFactory.java | 115 ++++++++ .../config/TestSchemaConfigurationSource.java | 9 +- .../rest/core/tests/utils/RestServerTest.java | 129 ++++++++- 7 files changed, 558 insertions(+), 34 deletions(-) create mode 100644 trace-server/org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests/src/org/eclipse/tracecompass/incubator/trace/server/jersey/rest/core/tests/stubs/TestDataProviderFactory.java diff --git a/trace-server/org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests/plugin.xml b/trace-server/org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests/plugin.xml index d740c328b..cbf808d03 100644 --- a/trace-server/org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests/plugin.xml +++ b/trace-server/org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests/plugin.xml @@ -8,4 +8,11 @@ id="org.eclipse.tracecompass.tmf.core.config.xmlsourcetype"> + + + + 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/ConfigurationManagerServiceTest.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/ConfigurationManagerServiceTest.java index 69b31b920..9b29ce1f3 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/ConfigurationManagerServiceTest.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/ConfigurationManagerServiceTest.java @@ -18,9 +18,7 @@ import static org.junit.Assert.fail; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; -import java.io.InputStream; import java.net.URISyntaxException; import java.net.URL; import java.util.Collections; @@ -36,7 +34,6 @@ import javax.ws.rs.core.Response; import org.eclipse.core.runtime.FileLocator; -import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.eclipse.jdt.annotation.NonNull; @@ -57,9 +54,7 @@ import org.junit.Test; import org.osgi.framework.Bundle; -import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import com.google.gson.Gson; /** @@ -70,7 +65,6 @@ @SuppressWarnings("restriction") public class ConfigurationManagerServiceTest extends RestServerTest { - private static final Bundle TEST_BUNDLE = Platform.getBundle("org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests"); private static final Bundle XML_CORE_TESTS = Platform.getBundle("org.eclipse.tracecompass.tmf.analysis.xml.core.tests"); private static final String UNKNOWN_TYPE = "test-test-test"; @@ -92,8 +86,6 @@ public class ConfigurationManagerServiceTest extends RestServerTest { private static final String EXPECTED_CONFIG_DESCRIPTION = "XML Data-driven analysis: " + VALID_NAME; private static final String PATH_TO_INVALID_PATH = getPath(PATH_INVALID + INVALID_XML_FILE); private static final String PATH_TO_VALID_PATH = getPath(PATH_VALID + VALID_XML_FILE); - private static final String CONFIG_FOLDER_NAME = "config"; - private static final String VALID_JSON_FILENAME = "custom-execution-analysis.json"; private static final String EXPECTED_JSON_CONFIG_NAME = "My Config Name"; private static final String EXPECTED_JSON_CONFIG_DESCRIPTION = "My Config Description"; @@ -377,15 +369,9 @@ private static Response createJsonConfig(String jsonFileName) throws URISyntaxEx .path(typeId) .path(CONFIG_INSTANCES_PATH); - IPath defaultPath = new org.eclipse.core.runtime.Path(CONFIG_FOLDER_NAME).append(jsonFileName); - URL url = FileLocator.find(TEST_BUNDLE, defaultPath, null); - File jsonFile = new File(FileLocator.toFileURL(url).toURI()); - try (InputStream inputStream = new FileInputStream(jsonFile)) { - ObjectMapper mapper = new ObjectMapper(); - Map params = mapper.readValue(inputStream, new TypeReference>() {}); - return endpoint.request(MediaType.APPLICATION_JSON) - .post(Entity.json(new ConfigurationQueryParameters(null, null, null, params))); - } + Map params = readParametersFromJson(jsonFileName); + return endpoint.request(MediaType.APPLICATION_JSON) + .post(Entity.json(new ConfigurationQueryParameters(null, null, null, params))); } private static Response updateConfig(String path, String id) { 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 4a48414a6..cfeb48f2b 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 @@ -18,6 +18,9 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -26,18 +29,24 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.Set; +import java.util.UUID; import java.util.stream.Collectors; import javax.ws.rs.ProcessingException; 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 javax.ws.rs.core.Response.Status; import org.eclipse.jdt.annotation.Nullable; 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.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; @@ -48,6 +57,7 @@ import org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests.stubs.TableColumnsOutputResponseStub; import org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests.stubs.TableLinesOutputResponseStub; import org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests.stubs.TableModelStub; +import org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests.stubs.TestDataProviderFactory; import org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests.stubs.TgEntryModelStub; import org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests.stubs.TgStatesOutputResponseStub; import org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests.stubs.TgTooltipOutputResponseStub; @@ -56,6 +66,7 @@ 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.TmfConfigurationSourceTypeStub; 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; @@ -63,9 +74,12 @@ 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.config.TestSchemaConfigurationSource; 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.config.ITmfConfiguration; +import org.eclipse.tracecompass.tmf.core.config.TmfConfiguration; import org.eclipse.tracecompass.tmf.core.model.filters.TimeQueryFilter; import org.junit.Test; @@ -113,6 +127,12 @@ public class DataProviderServiceTest extends RestServerTest { private static final String DEEP_SEARCH = "DEEP"; private static final String FILTER_QUERY = "test"; private static final int DIMMED_FILTER_TAG = 1; + private static final String UNKNOWN_EXP_UUID = UUID.nameUUIDFromBytes(Objects.requireNonNull("unknown.experiment.id".toString().getBytes(Charset.defaultCharset()))).toString(); + private static final String UNKNOWN_DP_ID = "unknown.dp.id"; + private static final String UNKNOWN_TYPE_ID = "unknown.config.type.id"; + + private static final String CONFIG_NAME = "My configuration"; + private static final String CONFIG_DESCRIPTION = "My description"; private static final List EXPECTED_XY_TREE_HEADERS = ImmutableList.of(new EntryHeaderStub("Process", "", null), new EntryHeaderStub("TID", "", null), new EntryHeaderStub("%", "", null), new EntryHeaderStub("Time", "", null)); @@ -120,6 +140,8 @@ public class DataProviderServiceTest extends RestServerTest { private static List SAMPLE_TOTAL_STATS_LABELS = ImmutableList.of("ust", "1 ns", "5.979 s", "10.845 ms", "196.299 ms", "1948", "21.127 s", "[1450193745774189602,1450193745774189603]", "[1450193722283061910,1450193728261604656]"); private static List SAMPLE_SELECTION_STATS_LABELS = ImmutableList.of("Selection", "49.665 µs", "5.979 s", "11.388 ms", "201.201 ms", "1854", "21.113 s", "[1450193730177271075,1450193730177320740]", "[1450193722283061910,1450193728261604656]"); + private static final GenericType> DP_CONFIG_TYPES_SET_TYPE = new GenericType>() {}; + /** * Test getting the data provider descriptors */ @@ -636,6 +658,250 @@ public void testTimeGraphMetaDataSerializer() { } } + /** + * Tests querying the data provider config types + */ + @SuppressWarnings("null") + @Test + public void testDataProviderConfigTypes() { + ExperimentModelStub exp = assertPostExperiment(CONTEXT_SWITCHES_UST_NOT_INITIALIZED_STUB.getName(), CONTEXT_SWITCHES_UST_NOT_INITIALIZED_STUB); + WebTarget configTypesEndpoint = getConfigEndpoint(exp.getUUID().toString(), TestDataProviderFactory.ID); + + // Get all config types + List configTypesListModel = configTypesEndpoint.request(MediaType.APPLICATION_JSON).get(DP_CONFIG_TYPES_SET_TYPE); + assertNotNull(configTypesListModel); + assertTrue(configTypesListModel.size() == 1); + Optional optional = configTypesListModel.stream().filter(config -> config.getId().equals(TestSchemaConfigurationSource.TYPE.getId())).findAny(); + assertTrue(optional.isPresent()); + + // Test Valid config type ID + WebTarget singleTypeEndpoint = configTypesEndpoint.path(optional.get().getId()); + TmfConfigurationSourceTypeStub singleConfigType = singleTypeEndpoint.request(MediaType.APPLICATION_JSON).get(TmfConfigurationSourceTypeStub.class); + assertNotNull(singleConfigType); + assertEquals(optional.get().getId(), singleConfigType.getId()); + + // Test config types for data provider that can't be configured + WebTarget configTypesEndpoint2 = getConfigEndpoint(exp.getUUID().toString(), CALL_STACK_DATAPROVIDER_ID); + List emptyConfigTypesListModel = configTypesEndpoint2.request(MediaType.APPLICATION_JSON).get(DP_CONFIG_TYPES_SET_TYPE); + assertNotNull(emptyConfigTypesListModel); + assertTrue(emptyConfigTypesListModel.isEmpty()); + } + + /** + * Tests error cases when querying data provider config types + */ + @Test + public void testDataProviderConfigTypesErrors() { + ExperimentModelStub exp = assertPostExperiment(CONTEXT_SWITCHES_UST_NOT_INITIALIZED_STUB.getName(), CONTEXT_SWITCHES_UST_NOT_INITIALIZED_STUB); + WebTarget configTypesEndpoint = getConfigEndpoint(UNKNOWN_EXP_UUID, TestDataProviderFactory.ID); + + // Unknown experiment + try (Response response = configTypesEndpoint.request(MediaType.APPLICATION_JSON).get()) { + assertNotNull(response); + assertEquals(Status.NOT_FOUND.getStatusCode(), response.getStatus()); + assertEquals(EndpointConstants.NO_SUCH_TRACE, response.readEntity(String.class)); + } + + WebTarget singleTypeEndpoint = configTypesEndpoint.path(TestSchemaConfigurationSource.TYPE.getId()); + try (Response response = singleTypeEndpoint.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 + configTypesEndpoint = getConfigEndpoint(exp.getUUID().toString(), UNKNOWN_DP_ID); + try (Response response = configTypesEndpoint.request(MediaType.APPLICATION_JSON).get()) { + assertNotNull(response); + assertEquals(Status.NOT_FOUND.getStatusCode(), response.getStatus()); + assertEquals(EndpointConstants.NO_SUCH_PROVIDER, response.readEntity(String.class)); + } + + singleTypeEndpoint = configTypesEndpoint.path(TestSchemaConfigurationSource.TYPE.getId()); + try (Response response = singleTypeEndpoint.request(MediaType.APPLICATION_JSON).get()) { + assertNotNull(response); + assertEquals(Status.NOT_FOUND.getStatusCode(), response.getStatus()); + assertEquals(EndpointConstants.NO_SUCH_PROVIDER, response.readEntity(String.class)); + } + + // Test config type is not applicable for another data provider + configTypesEndpoint = getConfigEndpoint(exp.getUUID().toString(), CALL_STACK_DATAPROVIDER_ID); + singleTypeEndpoint = configTypesEndpoint.path(TestSchemaConfigurationSource.TYPE.getId()); + try (Response response = singleTypeEndpoint.request(MediaType.APPLICATION_JSON).get()) { + assertNotNull(response); + assertEquals(Status.NOT_FOUND.getStatusCode(), response.getStatus()); + assertEquals(EndpointConstants.NO_SUCH_PROVIDER, response.readEntity(String.class)); + } + + configTypesEndpoint = getConfigEndpoint(exp.getUUID().toString(), TestDataProviderFactory.ID); + singleTypeEndpoint = configTypesEndpoint.path(UNKNOWN_TYPE_ID); + try (Response response = singleTypeEndpoint.request(MediaType.APPLICATION_JSON).get()) { + assertNotNull(response); + assertEquals(Status.NOT_FOUND.getStatusCode(), response.getStatus()); + assertEquals(EndpointConstants.NO_SUCH_CONFIGURATION_TYPE, response.readEntity(String.class)); + } + } + + /** + * Tests the creation and deletion of the derived data providers + * + * @throws URISyntaxException + * if such error occurs + * @throws IOException + * if such error occurs + */ + @SuppressWarnings("null") + @Test + public void testCreationDeletionOfDerivedDataProviders() throws IOException, URISyntaxException { + ExperimentModelStub exp = assertPostExperiment(CONTEXT_SWITCHES_UST_NOT_INITIALIZED_STUB.getName(), CONTEXT_SWITCHES_UST_NOT_INITIALIZED_STUB); + WebTarget dpCreationEndpoint = getDpCreationEndpoint(exp.getUUID().toString(), TestDataProviderFactory.ID); + Map params = readParametersFromJson(VALID_JSON_FILENAME); + ITmfConfiguration configuration = new TmfConfiguration.Builder() + .setName(CONFIG_NAME) + .setDescription(CONFIG_DESCRIPTION) + .setSourceTypeId(TestSchemaConfigurationSource.TYPE.getId()) + .setParameters(params) + .build(); + + // Successful creation + DataProviderDescriptorStub derivedDp = assertDpPost(dpCreationEndpoint, configuration); + assertNotNull(derivedDp); + + // Successful deletion + WebTarget dpDeletionEndpoint = dpCreationEndpoint.path(derivedDp.getId()); + try (Response response = dpDeletionEndpoint.request().delete()) { + assertNotNull(response); + assertEquals(Status.OK.getStatusCode(), response.getStatus()); + } + } + + /** + * Tests error cases when creating derived data providers + * + * @throws URISyntaxException + * if such error occurs + * @throws IOException + * if such error occurs + */ + @SuppressWarnings("null") + @Test + public void testCreationOfDerivedDataProvidersErrors() throws IOException, URISyntaxException { + ExperimentModelStub exp = assertPostExperiment(CONTEXT_SWITCHES_UST_NOT_INITIALIZED_STUB.getName(), CONTEXT_SWITCHES_UST_NOT_INITIALIZED_STUB); + WebTarget dpCreationEndpoint = getDpCreationEndpoint(UNKNOWN_EXP_UUID, TestDataProviderFactory.ID); + Map params = readParametersFromJson(VALID_JSON_FILENAME); + + TmfConfiguration.Builder builder = new TmfConfiguration.Builder() + .setName(CONFIG_NAME) + .setDescription(CONFIG_DESCRIPTION) + .setSourceTypeId(TestSchemaConfigurationSource.TYPE.getId()) + .setParameters(params); + ITmfConfiguration configuration = builder.build(); + + // Unknown experiment + try (Response response = assertDpPostWithErrors(dpCreationEndpoint, configuration)) { + assertEquals(Status.NOT_FOUND.getStatusCode(), response.getStatus()); + assertEquals(EndpointConstants.NO_SUCH_TRACE, response.readEntity(String.class)); + } + + // Unknown data provider + dpCreationEndpoint = getDpCreationEndpoint(exp.getUUID().toString(), UNKNOWN_DP_ID); + try (Response response = assertDpPostWithErrors(dpCreationEndpoint, configuration)) { + assertEquals(Status.NOT_FOUND.getStatusCode(), response.getStatus()); + assertEquals(EndpointConstants.NO_SUCH_PROVIDER, response.readEntity(String.class)); + } + + // Test config type is not applicable for another data provider + dpCreationEndpoint = getDpCreationEndpoint(exp.getUUID().toString(), CALL_STACK_DATAPROVIDER_ID); + try (Response response = assertDpPostWithErrors(dpCreationEndpoint, configuration)) { + assertEquals(Status.NOT_FOUND.getStatusCode(), response.getStatus()); + assertEquals(EndpointConstants.NO_SUCH_PROVIDER, response.readEntity(String.class)); + } + + // Invalid config type ID + dpCreationEndpoint = getDpCreationEndpoint(exp.getUUID().toString(), TestDataProviderFactory.ID); + builder = new TmfConfiguration.Builder() + .setName(CONFIG_NAME) + .setDescription(CONFIG_DESCRIPTION) + .setSourceTypeId(UNKNOWN_TYPE_ID) + .setParameters(params); + + configuration = builder.build(); + try (Response response = assertDpPostWithErrors(dpCreationEndpoint, configuration)) { + assertEquals(Status.NOT_FOUND.getStatusCode(), response.getStatus()); + assertEquals(EndpointConstants.NO_SUCH_CONFIGURATION_TYPE, response.readEntity(String.class)); + } + } + + /** + * Tests error cases when deleting derived data providers + * + * @throws URISyntaxException + * if such error occurs + * @throws IOException + * if such error occurs + */ + @SuppressWarnings("null") + @Test + public void testDeletionOfDerivedDataProvidersErrors() throws IOException, URISyntaxException { + ExperimentModelStub exp = assertPostExperiment(CONTEXT_SWITCHES_UST_NOT_INITIALIZED_STUB.getName(), CONTEXT_SWITCHES_UST_NOT_INITIALIZED_STUB); + + // Unknown experiment + WebTarget dpCreationEndpoint = getDpCreationEndpoint(UNKNOWN_EXP_UUID, TestDataProviderFactory.ID); + WebTarget dpDeletionEndpoint = dpCreationEndpoint.path(UNKNOWN_DP_ID); + try (Response response = dpDeletionEndpoint.request().delete()) { + assertNotNull(response); + assertEquals(Status.NOT_FOUND.getStatusCode(), response.getStatus()); + assertEquals(EndpointConstants.NO_SUCH_TRACE, response.readEntity(String.class)); + } + + // Unknown input data provider + dpCreationEndpoint = getDpCreationEndpoint(exp.getUUID().toString(), UNKNOWN_DP_ID); + dpDeletionEndpoint = dpCreationEndpoint.path(UNKNOWN_DP_ID); + try (Response response = dpDeletionEndpoint.request().delete()) { + assertNotNull(response); + assertEquals(Status.NOT_FOUND.getStatusCode(), response.getStatus()); + assertEquals(EndpointConstants.NO_SUCH_PROVIDER + ": " + UNKNOWN_DP_ID, response.readEntity(String.class)); + } + + // Unknown derived data provider + dpCreationEndpoint = getDpCreationEndpoint(exp.getUUID().toString(), TestDataProviderFactory.ID); + dpDeletionEndpoint = dpCreationEndpoint.path(UNKNOWN_DP_ID); + try (Response response = dpDeletionEndpoint.request().delete()) { + assertNotNull(response); + assertEquals(Status.NOT_FOUND.getStatusCode(), response.getStatus()); + assertEquals(EndpointConstants.NO_SUCH_DERIVED_PROVIDER + ": " + UNKNOWN_DP_ID, response.readEntity(String.class)); + } + + Map params = readParametersFromJson(VALID_JSON_FILENAME); + ITmfConfiguration configuration = new TmfConfiguration.Builder() + .setName("My name") + .setDescription("My Description") + .setSourceTypeId(TestSchemaConfigurationSource.TYPE.getId()) + .setParameters(params) + .build(); + + // Successful creation + DataProviderDescriptorStub derivedDp = assertDpPost(dpCreationEndpoint, configuration); + assertNotNull(derivedDp); + + // Test config type is not applicable for another data provider + dpCreationEndpoint = getDpCreationEndpoint(exp.getUUID().toString(), CALL_STACK_DATAPROVIDER_ID); + dpDeletionEndpoint = dpCreationEndpoint.path(derivedDp.getId()); + try (Response response = dpDeletionEndpoint.request().delete()) { + assertNotNull(response); + assertEquals(Status.NOT_FOUND.getStatusCode(), response.getStatus()); + assertEquals(EndpointConstants.NO_SUCH_PROVIDER, response.readEntity(String.class)); + } + + // Successful deletion + dpCreationEndpoint = getDpCreationEndpoint(exp.getUUID().toString(), TestDataProviderFactory.ID); + dpDeletionEndpoint = dpCreationEndpoint.path(derivedDp.getId()); + try (Response response = dpDeletionEndpoint.request().delete()) { + assertNotNull(response); + assertEquals(Status.OK.getStatusCode(), response.getStatus()); + } + } + private static void verifyMetadata(Map> metadata, String key, Class clazz) { Collection col = metadata.get(key); assertNotNull(key, col); 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/DataProviderDescriptorStub.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/DataProviderDescriptorStub.java index a70b695fc..f3550cc27 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/stubs/DataProviderDescriptorStub.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/DataProviderDescriptorStub.java @@ -33,14 +33,18 @@ public class DataProviderDescriptorStub implements Serializable { * Generated Serial Version UID */ private static final long serialVersionUID = -6380168132081665386L; + private final String fParentId; private final String fId; private final String fName; private final String fDescription; private final String fTypeId; + private final TmfConfigurationStub fConfiguration; /** * {@link JsonCreator} Constructor for final fields * + * @param parentId + * the parentId * @param id * the id * @param name @@ -49,17 +53,32 @@ public class DataProviderDescriptorStub implements Serializable { * the help text * @param type * the type id + * @param configuration + * the configuration * */ @JsonCreator - public DataProviderDescriptorStub(@JsonProperty("id") String id, + public DataProviderDescriptorStub(@JsonProperty("parentId") String parentId, + @JsonProperty("id") String id, @JsonProperty("name") String name, @JsonProperty("description") String description, - @JsonProperty("type") String type) { + @JsonProperty("type") String type, + @JsonProperty("configuration") TmfConfigurationStub configuration) { + fParentId = parentId; fId = id; fName = name; fDescription = description; fTypeId = type; + fConfiguration = configuration; + } + + /** + * Gets the parent ID + * + * @return the parent ID + */ + public String getParentId() { + return fParentId; } /** @@ -98,15 +117,24 @@ public String getTypeId() { return fTypeId; } + /** + * Gets the configuration + * + * @return the type ID + */ + public TmfConfigurationStub getConfiguration() { + return fConfiguration; + } + @Override public String toString() { - return "DataProviderDescriptorStub[fId=" + getId() + ", fName=" + fName + ", fDescription=" + fDescription - + ", fTypeId=" + fTypeId+ "]"; + return "DataProviderDescriptorStub[fParentId=" + getParentId() + ", fId=" + getId() + ", fName=" + fName + ", fDescription=" + fDescription + + ", fTypeId=" + fTypeId + ", fConfiguration=" + getConfiguration() + "]"; } @Override public int hashCode() { - return Objects.hash(fId, fName, fDescription, fTypeId); + return Objects.hash(fParentId, fId, fName, fDescription, fTypeId, fConfiguration); } @Override @@ -121,6 +149,9 @@ public boolean equals(Object obj) { if (obj instanceof DataProviderDescriptorStub) { DataProviderDescriptorStub other = (DataProviderDescriptorStub) obj; + if (!Objects.equals(fParentId, other.fParentId)) { + return false; + } if (!Objects.equals(fId, other.fId)) { return false; } @@ -130,7 +161,10 @@ public boolean equals(Object obj) { if (!Objects.equals(fDescription, other.fDescription)) { return false; } - if (Objects.equals(fTypeId, other.fTypeId)) { + if (!Objects.equals(fTypeId, other.fTypeId)) { + return false; + } + if (Objects.equals(fConfiguration, other.fConfiguration)) { return true; } } 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/TestDataProviderFactory.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/TestDataProviderFactory.java new file mode 100644 index 000000000..d46e3ab4e --- /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/TestDataProviderFactory.java @@ -0,0 +1,115 @@ +/******************************************************************************* + * Copyright (c) 2018, + * 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.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests.stubs.config.TestSchemaConfigurationSource; +import org.eclipse.tracecompass.tmf.core.config.ITmfConfiguration; +import org.eclipse.tracecompass.tmf.core.config.ITmfConfigurationSourceType; +import org.eclipse.tracecompass.tmf.core.config.ITmfDataProviderConfigurator; +import org.eclipse.tracecompass.tmf.core.config.TmfConfiguration; +import org.eclipse.tracecompass.tmf.core.dataprovider.IDataProviderDescriptor; +import org.eclipse.tracecompass.tmf.core.dataprovider.IDataProviderDescriptor.ProviderType; +import org.eclipse.tracecompass.tmf.core.dataprovider.IDataProviderFactory; +import org.eclipse.tracecompass.tmf.core.exceptions.TmfConfigurationException; +import org.eclipse.tracecompass.tmf.core.model.DataProviderDescriptor; +import org.eclipse.tracecompass.tmf.core.model.tree.ITmfTreeDataModel; +import org.eclipse.tracecompass.tmf.core.model.tree.ITmfTreeDataProvider; +import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; + +/** + * Test data provider factory + */ +public class TestDataProviderFactory implements IDataProviderFactory, ITmfDataProviderConfigurator{ + + /** The ID of the factory */ + public static final String ID = "org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests.stubs.TestDataProviderFactory"; + + /** Name to test already exists */ + public static final String ALREADY_EXISTS_NAME = "ALREADY_EXISTS"; + + private static final String CONFIGURATOR_NAME = "Test Configurator"; //$NON-NLS-1$ + private static final String CONFIGURATOR_DESCRIPTION = "Configure custom test analysis"; //$NON-NLS-1$ + + private static final String DERIVED_CONFIGURATOR_NAME = "Derived Test DP"; //$NON-NLS-1$ + private static final String DERIVED_CONFIGURATOR_DESCRIPTION = "Derived custom test analysis"; //$NON-NLS-1$ + + private IDataProviderDescriptor fDerivedDescriptor; + + /** + * Default constructor + */ + public TestDataProviderFactory() { + } + + @Override + public @Nullable ITmfTreeDataProvider createProvider(@NonNull ITmfTrace trace) { + return null; + } + + private static final IDataProviderDescriptor DESCRIPTOR = new DataProviderDescriptor.Builder() + .setId(ID) + .setName(CONFIGURATOR_NAME) + .setDescription(CONFIGURATOR_DESCRIPTION) + .setProviderType(ProviderType.DATA_TREE) + .build(); + + @SuppressWarnings("null") + @Override + public @NonNull List<@NonNull ITmfConfigurationSourceType> getConfigurationSourceTypes() { + return List.of(TestSchemaConfigurationSource.TYPE); + } + + @Override + public @NonNull IDataProviderDescriptor createDataProviderDescriptors(@NonNull ITmfTrace trace, @NonNull ITmfConfiguration configuration) throws TmfConfigurationException { + if (configuration.getName().equals(TmfConfiguration.UNKNOWN)) { + throw new TmfConfigurationException("Missing configuration name"); //$NON-NLS-1$ + } + + if (configuration.getSourceTypeId().equals(TmfConfiguration.UNKNOWN)) { + throw new TmfConfigurationException("Missing configuration type"); //$NON-NLS-1$ + } + fDerivedDescriptor = new DataProviderDescriptor.Builder() + .setParentId(ID) + .setId(ID + configuration.getId()) + .setConfiguration(configuration) + .setName(DERIVED_CONFIGURATOR_NAME + ", " + configuration.getName()) + .setDescription(DERIVED_CONFIGURATOR_DESCRIPTION + ", " + configuration.getDescription()) + .setProviderType(ProviderType.TIME_GRAPH) + .build(); + return fDerivedDescriptor; + } + + @Override + public void removeDataProviderDescriptor(@NonNull ITmfTrace trace, @NonNull IDataProviderDescriptor descriptor) throws TmfConfigurationException { + ITmfConfiguration creationConfiguration = descriptor.getConfiguration(); + if (creationConfiguration == null) { + throw new TmfConfigurationException("Data provider was not created by a configuration"); //$NON-NLS-1$ + } + fDerivedDescriptor = null; + } + + @Override + public @NonNull Collection getDescriptors(@NonNull ITmfTrace trace) { + List descriptor = new ArrayList<>(); + descriptor.add(DESCRIPTOR); + if (fDerivedDescriptor != null) { + descriptor.add(fDerivedDescriptor); + } + return descriptor; + } + +} 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/config/TestSchemaConfigurationSource.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/config/TestSchemaConfigurationSource.java index 262c91cb9..a8b5b4fba 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/stubs/config/TestSchemaConfigurationSource.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/config/TestSchemaConfigurationSource.java @@ -42,7 +42,10 @@ */ public class TestSchemaConfigurationSource implements ITmfConfigurationSource { - private static final @NonNull ITmfConfigurationSourceType fType; + /** + * The Configuration type + */ + public static final @NonNull ITmfConfigurationSourceType TYPE; private static final @NonNull String TEST_ANALYSIS_TYPE_ID = "org.eclipse.tracecompass.tmf.core.config.testschemasourcetype"; //$NON-NLS-1$ private static final @NonNull String NAME = nullToEmptyString("Test Schema Type"); //$NON-NLS-1$ @@ -64,7 +67,7 @@ public class TestSchemaConfigurationSource implements ITmfConfigurationSource { } catch (URISyntaxException | IOException e) { e.printStackTrace(); } - fType = new TmfConfigurationSourceType.Builder() + TYPE = new TmfConfigurationSourceType.Builder() .setId(TEST_ANALYSIS_TYPE_ID) .setDescription(DESCRIPTION) .setName(NAME) @@ -80,7 +83,7 @@ public TestSchemaConfigurationSource() { @Override public @NonNull ITmfConfigurationSourceType getConfigurationSourceType() { - return fType; + return TYPE; } @Override 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/utils/RestServerTest.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/utils/RestServerTest.java index b0008d6a3..94cc41d1b 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/utils/RestServerTest.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/utils/RestServerTest.java @@ -13,7 +13,12 @@ import static org.junit.Assert.assertEquals; +import java.io.File; +import java.io.FileInputStream; import java.io.IOException; +import java.io.InputStream; +import java.net.URISyntaxException; +import java.net.URL; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -30,6 +35,9 @@ import javax.ws.rs.core.Response; import org.eclipse.core.runtime.FileLocator; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Platform; +import org.eclipse.tracecompass.incubator.internal.trace.server.jersey.rest.core.model.views.ConfigurationQueryParameters; 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; @@ -38,11 +46,15 @@ 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.config.ITmfConfiguration; import org.eclipse.tracecompass.tmf.core.dataprovider.IDataProviderDescriptor.ProviderType; import org.junit.After; import org.junit.Before; import org.junit.BeforeClass; +import org.osgi.framework.Bundle; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider; import com.google.common.collect.ImmutableList; @@ -56,6 +68,9 @@ 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)); + private static final Bundle TEST_BUNDLE = Platform.getBundle("org.eclipse.tracecompass.incubator.trace.server.jersey.rest.core.tests"); + private static final String CONFIG_FOLDER_NAME = "config"; + /** * Traces endpoint path (relative to application). */ @@ -120,6 +135,11 @@ public abstract class RestServerTest { */ public static final String TABLE_LINE_PATH = "lines"; + /** + * ConfigTypes path + */ + public static final String DP_CONFIG_TYPES_PATH = "configTypes"; + /** * name constant */ @@ -144,6 +164,11 @@ public abstract class RestServerTest { */ public static final String CONFIG_INSTANCES_PATH = "configs"; + /** + * Filename with valid json configuration + */ + public static final String VALID_JSON_FILENAME = "custom-execution-analysis.json"; + private static final GenericType> TRACE_MODEL_SET_TYPE = new GenericType>() { }; private static final GenericType> EXPERIMENT_MODEL_SET_TYPE = new GenericType>() { @@ -278,18 +303,18 @@ public static void beforeTest() throws IOException { ARM_64_KERNEL_STUB = new TraceModelStub(ARM_64_KERNEL_NAME, arm64Path, ARM_64_KERNEL_PROPERTIES); ImmutableList.Builder b = ImmutableList.builder(); - b.add(new DataProviderDescriptorStub("org.eclipse.tracecompass.internal.analysis.timing.core.segmentstore.scatter.dataprovider:org.eclipse.linuxtools.lttng2.ust.analysis.callstack", + b.add(new DataProviderDescriptorStub(null, "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", + ProviderType.TREE_TIME_XY.name(), null)); + b.add(new DataProviderDescriptorStub(null,"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", + ProviderType.TIME_GRAPH.name(), null)); + b.add(new DataProviderDescriptorStub(null,"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())); + ProviderType.TREE_TIME_XY.name(), null)); EXPECTED_DATA_PROVIDER_DESCRIPTOR = b.build(); } @@ -464,8 +489,7 @@ public static WebTarget getXYTreeEndpoint(String expUUID, String dataProviderId) /** * Get the {@link WebTarget} for the XY series endpoint. * - * @param expUUID - * Experiment UUID + * @param expUUID * Experiment UUID * @param dataProviderId * Data provider ID * @return The XY series endpoint @@ -479,6 +503,39 @@ public static WebTarget getXYSeriesEndpoint(String expUUID, String dataProviderI .path(XY_SERIES_PATH); } + /** + * Get the {@link WebTarget} for the configTypes endpoint of a given data provider. + * + * @param expUUID + * Experiment UUID + * @param dataProviderId + * Data provider ID + * @return The time graph tree configTypes endpoint + */ + public static WebTarget getConfigEndpoint(String expUUID, String dataProviderId) { + return getApplicationEndpoint().path(EXPERIMENTS) + .path(expUUID) + .path(OUTPUTS_PATH) + .path(dataProviderId) + .path(DP_CONFIG_TYPES_PATH); + } + + /** + * Get the {@link WebTarget} for data provide creation endpoint of a given data provider. + * + * @param expUUID + * Experiment UUID + * @param dataProviderId + * Data provider ID + * @return The time graph tree configTypes endpoint + */ + public static WebTarget getDpCreationEndpoint(String expUUID, String dataProviderId) { + return getApplicationEndpoint().path(EXPERIMENTS) + .path(expUUID) + .path(OUTPUTS_PATH) + .path(dataProviderId); + } + /** * Get the traces currently open on the server. * @@ -559,4 +616,60 @@ public static ExperimentModelStub assertPostExperiment(String name, TraceModelSt assertEquals("Failed to POST experiment " + name + ", error code=" + response.getStatus(), 200, response.getStatus()); return response.readEntity(ExperimentModelStub.class); } + + /** + * @param dpConfigEndpoint + * the dp config endpoint to create a derived data provider + * @param configuration + * the configuration with input parameters to post + * @return the derived data provider descriptor stub + */ + @SuppressWarnings("null") + public static DataProviderDescriptorStub assertDpPost(WebTarget dpConfigEndpoint, ITmfConfiguration configuration) { + try (Response response = dpConfigEndpoint.request().post(Entity.json( + new ConfigurationQueryParameters(configuration.getName(), configuration.getDescription(), configuration.getSourceTypeId(), configuration.getParameters())))) { + int code = response.getStatus(); + assertEquals("Failed to POST " + configuration.getName() + ", error code=" + code, 200, code); + DataProviderDescriptorStub result = response.readEntity(DataProviderDescriptorStub.class); + assertEquals(configuration.getName(), result.getConfiguration().getName()); + assertEquals(configuration.getDescription(), result.getConfiguration().getDescription()); + assertEquals(configuration.getSourceTypeId(), result.getConfiguration().getSourceTypeId()); + assertEquals(configuration.getParameters(), result.getConfiguration().getParameters()); + return result; + } + } + + /** + * Request to create a derived DP but will cause errors + * + * @param dpConfigEndpoint + * the dp config endpoint to create a derived data provider + * @param configuration + * the configuration with input parameters to post + * @return error code + */ + @SuppressWarnings("null") + public static Response assertDpPostWithErrors(WebTarget dpConfigEndpoint, ITmfConfiguration configuration) { + return dpConfigEndpoint.request().post(Entity.json( + new ConfigurationQueryParameters(configuration.getName(), configuration.getDescription(), configuration.getSourceTypeId(), configuration.getParameters()))); + } + + /** + * @param jsonFileName + * the json file to read in config folder + * @return json parameters as Map + * @throws IOException + * if such exception occurs + * @throws URISyntaxException + * if such exception occurs + */ + public static Map readParametersFromJson(String jsonFileName) throws IOException, URISyntaxException { + IPath defaultPath = new org.eclipse.core.runtime.Path(CONFIG_FOLDER_NAME).append(jsonFileName); + URL url = FileLocator.find(TEST_BUNDLE, defaultPath, null); + File jsonFile = new File(FileLocator.toFileURL(url).toURI()); + try (InputStream inputStream = new FileInputStream(jsonFile)) { + ObjectMapper mapper = new ObjectMapper(); + return mapper.readValue(inputStream, new TypeReference>() {}); + } + } }