blob: 25acb29ff0d6f626f1a962d0996992bd527b3990 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.olingo.server.core.uri.validator;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import java.util.Collections;
import org.apache.olingo.commons.api.edm.Edm;
import org.apache.olingo.commons.api.edmx.EdmxReference;
import org.apache.olingo.commons.api.http.HttpMethod;
import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.core.uri.parser.Parser;
import org.apache.olingo.server.core.uri.parser.UriParserException;
import org.apache.olingo.server.core.uri.parser.UriParserSemanticException;
import org.apache.olingo.server.core.uri.testutil.TestUriValidator;
import org.apache.olingo.server.tecsvc.provider.EdmTechProvider;
import org.junit.Test;
public class UriValidatorTest {
private static final String URI_ACTION_NO_RETURN = "AIRT";
private static final String URI_ACTION_PRIM = "AIRTString";
private static final String URI_ACTION_COLL_PRIM = "AIRTCollStringTwoParam";
private static final String URI_ACTION_CT = "AIRTCTTwoPrimParam";
private static final String URI_ACTION_COLL_CT = "AIRTCollCTTwoPrimParam";
private static final String URI_ACTION_ENTITY = "AIRTESAllPrimParam";
private static final String URI_ACTION_ES = "AIRTCollESAllPrimParam";
// TODO: bound actions
@SuppressWarnings("unused")
private static final String URI_BOUND_ACTION_ENTITY_SET = "ESTwoKeyNav/Namespace1_Alias.BAESTwoKeyNavRTESTwoKeyNav";
@SuppressWarnings("unused")
private static final String URI_BOUND_ACTION_ENTITY = "ESAllPrim/Namespace1_Alias.BAESAllPrimRTETAllPrim";
private static final String URI_ALL = "$all";
private static final String URI_BATCH = "$batch";
private static final String URI_CROSSJOIN = "$crossjoin(ESAllPrim)";
private static final String URI_ENTITY_ID = "$entity/Namespace1_Alias.ETBase";
private static final String URI_METADATA = "$metadata";
private static final String URI_SERVICE = "";
private static final String URI_ENTITY_SET = "ESAllPrim";
private static final String URI_ENTITY_SET_COUNT = "ESAllPrim/$count";
private static final String URI_ENTITY = "ESAllPrim(1)";
private static final String URI_MEDIA_STREAM = "ESMedia(1)/$value";
private static final String URI_REFERENCES = "ESAllPrim/$ref";
private static final String URI_REFERENCE = "ESAllPrim(1)/$ref";
private static final String URI_PROPERTY_COMPLEX = "ESCompComp(1)/PropertyComp";
private static final String URI_PROPERTY_COMPLEX_COLLECTION =
"ESCompCollComp(1)/PropertyComp/CollPropertyComp";
private static final String URI_PROPERTY_COMPLEX_COLLECTION_COUNT =
"ESCompCollComp(1)/PropertyComp/CollPropertyComp/$count";
private static final String URI_PROPERTY_PRIMITIVE = "ESAllPrim(1)/PropertyString";
private static final String URI_PROPERTY_PRIMITIVE_COLLECTION = "ESCollAllPrim(1)/CollPropertyString";
private static final String URI_PROPERTY_PRIMITIVE_COLLECTION_COUNT =
"ESCollAllPrim(1)/CollPropertyString/$count";
private static final String URI_PROPERTY_PRIMITIVE_VALUE = "ESAllPrim(1)/PropertyString/$value";
private static final String URI_SINGLETON = "SI";
private static final String URI_NAV_ENTITY = "ESKeyNav(1)/NavPropertyETKeyNavOne";
private static final String URI_NAV_ENTITY_SET = "ESKeyNav(1)/NavPropertyETKeyNavMany";
private static final String URI_FI_ENTITY_SET = "FICRTCollESMedia()";
private static final String URI_FI_ENTITY = "FICRTETTwoKeyNavParam(ParameterInt16=1)";
private static final String URI_FI_ENTITY_SET_KEY = "FICRTCollESMedia()(3)";
private static final String QO_FILTER = "$filter='1' eq '1'";
private static final String QO_FORMAT = "$format=bla/bla";
private static final String QO_EXPAND = "$expand=*";
private static final String QO_ID = "$id=ESAllPrim(1)";
private static final String QO_COUNT = "$count=true";
private static final String QO_ORDERBY = "$orderby=true";
private static final String QO_SEARCH = "$search=bla";
private static final String QO_SELECT = "$select=*";
private static final String QO_SKIP = "$skip=3";
private static final String QO_SKIPTOKEN = "$skiptoken=123";
private static final String QO_TOP = "$top=1";
private static final String QO_APPLY = "$apply=identity";
private final String[][] urisWithValidSystemQueryOptions = {
{ URI_ALL, QO_FILTER }, { URI_ALL, QO_FORMAT }, { URI_ALL, QO_EXPAND }, { URI_ALL, QO_COUNT },
{ URI_ALL, QO_ORDERBY }, { URI_ALL, QO_SEARCH }, { URI_ALL, QO_SELECT }, { URI_ALL, QO_SKIP },
{ URI_ALL, QO_SKIPTOKEN }, { URI_ALL, QO_TOP }, { URI_ALL, QO_APPLY },
{ URI_CROSSJOIN, QO_FILTER }, { URI_CROSSJOIN, QO_FORMAT },
{ URI_CROSSJOIN, QO_EXPAND }, { URI_CROSSJOIN, QO_COUNT }, { URI_CROSSJOIN, QO_ORDERBY },
{ URI_CROSSJOIN, QO_SEARCH }, { URI_CROSSJOIN, QO_SELECT }, { URI_CROSSJOIN, QO_SKIP },
{ URI_CROSSJOIN, QO_SKIPTOKEN }, { URI_CROSSJOIN, QO_TOP }, { URI_CROSSJOIN, QO_APPLY },
{ URI_ENTITY_ID, QO_ID, QO_FORMAT }, { URI_ENTITY_ID, QO_ID }, { URI_ENTITY_ID, QO_ID, QO_EXPAND },
{ URI_ENTITY_ID, QO_ID, QO_SELECT },
{ URI_METADATA, QO_FORMAT },
{ URI_SERVICE, QO_FORMAT },
{ URI_ENTITY_SET, QO_FILTER }, { URI_ENTITY_SET, QO_FORMAT }, { URI_ENTITY_SET, QO_EXPAND },
{ URI_ENTITY_SET, QO_COUNT }, { URI_ENTITY_SET, QO_ORDERBY }, { URI_ENTITY_SET, QO_SEARCH },
{ URI_ENTITY_SET, QO_SELECT }, { URI_ENTITY_SET, QO_SKIP }, { URI_ENTITY_SET, QO_SKIPTOKEN },
{ URI_ENTITY_SET, QO_TOP }, { URI_ENTITY_SET, QO_APPLY },
{ URI_ENTITY_SET_COUNT, QO_FILTER }, { URI_ENTITY_SET_COUNT, QO_SEARCH }, { URI_ENTITY_SET_COUNT, QO_APPLY },
{ URI_ENTITY, QO_FORMAT }, { URI_ENTITY, QO_EXPAND }, { URI_ENTITY, QO_SELECT },
{ URI_REFERENCES, QO_FILTER }, { URI_REFERENCES, QO_FORMAT }, { URI_REFERENCES, QO_ORDERBY },
{ URI_REFERENCES, QO_SEARCH }, { URI_REFERENCES, QO_SKIP }, { URI_REFERENCES, QO_SKIPTOKEN },
{ URI_REFERENCES, QO_TOP }, { URI_REFERENCES, QO_COUNT },
{ URI_REFERENCE, QO_FORMAT },
{ URI_PROPERTY_COMPLEX, QO_FORMAT }, { URI_PROPERTY_COMPLEX, QO_SELECT }, { URI_PROPERTY_COMPLEX, QO_EXPAND },
{ URI_PROPERTY_COMPLEX_COLLECTION, QO_FILTER }, { URI_PROPERTY_COMPLEX_COLLECTION, QO_FORMAT },
{ URI_PROPERTY_COMPLEX_COLLECTION, QO_EXPAND }, { URI_PROPERTY_COMPLEX_COLLECTION, QO_COUNT },
{ URI_PROPERTY_COMPLEX_COLLECTION, QO_ORDERBY }, { URI_PROPERTY_COMPLEX_COLLECTION, QO_SELECT },
{ URI_PROPERTY_COMPLEX_COLLECTION, QO_SKIP }, { URI_PROPERTY_COMPLEX_COLLECTION, QO_SKIPTOKEN },
{ URI_PROPERTY_COMPLEX_COLLECTION, QO_TOP }, { URI_PROPERTY_COMPLEX_COLLECTION, QO_APPLY },
{ URI_PROPERTY_COMPLEX_COLLECTION_COUNT, QO_FILTER }, { URI_PROPERTY_COMPLEX_COLLECTION_COUNT, QO_APPLY },
{ URI_PROPERTY_PRIMITIVE, QO_FORMAT },
{ URI_PROPERTY_PRIMITIVE_COLLECTION, QO_FILTER }, { URI_PROPERTY_PRIMITIVE_COLLECTION, QO_FORMAT },
{ URI_PROPERTY_PRIMITIVE_COLLECTION, QO_COUNT }, { URI_PROPERTY_PRIMITIVE_COLLECTION, QO_ORDERBY },
{ URI_PROPERTY_PRIMITIVE_COLLECTION, QO_SKIP }, { URI_PROPERTY_PRIMITIVE_COLLECTION, QO_SKIPTOKEN },
{ URI_PROPERTY_PRIMITIVE_COLLECTION, QO_TOP },
{ URI_PROPERTY_PRIMITIVE_COLLECTION_COUNT, QO_FILTER },
{ URI_PROPERTY_PRIMITIVE_VALUE, QO_FORMAT },
{ URI_SINGLETON, QO_FORMAT }, { URI_SINGLETON, QO_EXPAND }, { URI_SINGLETON, QO_SELECT },
{ URI_NAV_ENTITY, QO_FORMAT }, { URI_NAV_ENTITY, QO_EXPAND }, { URI_NAV_ENTITY, QO_SELECT },
{ URI_NAV_ENTITY_SET, QO_FILTER }, { URI_NAV_ENTITY_SET, QO_FORMAT }, { URI_NAV_ENTITY_SET, QO_EXPAND },
{ URI_NAV_ENTITY_SET, QO_COUNT }, { URI_NAV_ENTITY_SET, QO_ORDERBY },
{ URI_NAV_ENTITY_SET, QO_SEARCH }, { URI_NAV_ENTITY_SET, QO_SELECT }, { URI_NAV_ENTITY_SET, QO_SKIP },
{ URI_NAV_ENTITY_SET, QO_SKIPTOKEN }, { URI_NAV_ENTITY_SET, QO_TOP }, { URI_NAV_ENTITY_SET, QO_APPLY },
{ URI_FI_ENTITY_SET, QO_FILTER }, { URI_FI_ENTITY_SET, QO_FORMAT }, { URI_FI_ENTITY_SET, QO_EXPAND },
{ URI_FI_ENTITY_SET, QO_COUNT }, { URI_FI_ENTITY_SET, QO_ORDERBY }, { URI_FI_ENTITY_SET, QO_SEARCH },
{ URI_FI_ENTITY_SET, QO_SELECT }, { URI_FI_ENTITY_SET, QO_SKIP }, { URI_FI_ENTITY_SET, QO_SKIPTOKEN },
{ URI_FI_ENTITY_SET, QO_TOP }, { URI_FI_ENTITY_SET, QO_APPLY },
{ URI_FI_ENTITY, QO_FORMAT }, { URI_FI_ENTITY, QO_EXPAND }, { URI_FI_ENTITY, QO_SELECT },
{ URI_FI_ENTITY_SET_KEY, QO_FORMAT }, { URI_FI_ENTITY_SET_KEY, QO_EXPAND }, { URI_FI_ENTITY_SET_KEY, QO_SELECT },
{ "FINRTInt16()", QO_FORMAT },
{ "FICRTCollString()", QO_FORMAT },
{ "FICRTCTTwoPrim()", QO_FORMAT },
{ "FICRTCollCTTwoPrim()", QO_FORMAT }
};
private final String[][] urisWithNonValidSystemQueryOptions = {
{ URI_ALL, QO_ID },
{ URI_BATCH, QO_FILTER }, { URI_BATCH, QO_FORMAT }, { URI_BATCH, QO_ID }, { URI_BATCH, QO_EXPAND },
{ URI_BATCH, QO_COUNT }, { URI_BATCH, QO_ORDERBY }, { URI_BATCH, QO_SEARCH }, { URI_BATCH, QO_SELECT },
{ URI_BATCH, QO_SKIP }, { URI_BATCH, QO_SKIPTOKEN }, { URI_BATCH, QO_TOP }, { URI_BATCH, QO_APPLY },
{ URI_CROSSJOIN, QO_ID },
{ URI_ENTITY_ID, QO_ID, QO_FILTER },
{ URI_ENTITY_ID, QO_ID, QO_COUNT }, { URI_ENTITY_ID, QO_ID, QO_ORDERBY }, { URI_ENTITY_ID, QO_ID, QO_SEARCH },
{ URI_ENTITY_ID, QO_ID, QO_SKIP }, { URI_ENTITY_ID, QO_ID, QO_SKIPTOKEN }, { URI_ENTITY_ID, QO_ID, QO_TOP },
{ URI_ENTITY_ID, QO_ID, QO_APPLY },
{ URI_METADATA, QO_FILTER }, { URI_METADATA, QO_ID }, { URI_METADATA, QO_EXPAND },
{ URI_METADATA, QO_COUNT }, { URI_METADATA, QO_ORDERBY }, { URI_METADATA, QO_SEARCH },
{ URI_METADATA, QO_SELECT }, { URI_METADATA, QO_SKIP }, { URI_METADATA, QO_SKIPTOKEN },
{ URI_METADATA, QO_TOP }, { URI_METADATA, QO_APPLY },
{ URI_SERVICE, QO_FILTER }, { URI_SERVICE, QO_ID }, { URI_SERVICE, QO_EXPAND }, { URI_SERVICE, QO_COUNT },
{ URI_SERVICE, QO_ORDERBY }, { URI_SERVICE, QO_SEARCH }, { URI_SERVICE, QO_SELECT },
{ URI_SERVICE, QO_SKIP }, { URI_SERVICE, QO_SKIPTOKEN }, { URI_SERVICE, QO_TOP }, { URI_SERVICE, QO_APPLY },
{ URI_ENTITY_SET, QO_ID },
{ URI_ENTITY_SET_COUNT, QO_FORMAT }, { URI_ENTITY_SET_COUNT, QO_ID },
{ URI_ENTITY_SET_COUNT, QO_EXPAND }, { URI_ENTITY_SET_COUNT, QO_COUNT },
{ URI_ENTITY_SET_COUNT, QO_ORDERBY },
{ URI_ENTITY_SET_COUNT, QO_SELECT }, { URI_ENTITY_SET_COUNT, QO_SKIP }, { URI_ENTITY_SET_COUNT, QO_SKIPTOKEN },
{ URI_ENTITY_SET_COUNT, QO_TOP },
{ URI_ENTITY, QO_FILTER }, { URI_ENTITY, QO_ID }, { URI_ENTITY, QO_COUNT }, { URI_ENTITY, QO_ORDERBY },
{ URI_ENTITY, QO_SEARCH }, { URI_ENTITY, QO_SKIP }, { URI_ENTITY, QO_SKIPTOKEN }, { URI_ENTITY, QO_TOP },
{ URI_ENTITY, QO_APPLY },
{ URI_MEDIA_STREAM, QO_FILTER }, { URI_MEDIA_STREAM, QO_FORMAT }, { URI_MEDIA_STREAM, QO_ID },
{ URI_MEDIA_STREAM, QO_EXPAND }, { URI_MEDIA_STREAM, QO_COUNT }, { URI_MEDIA_STREAM, QO_ORDERBY },
{ URI_MEDIA_STREAM, QO_SEARCH }, { URI_MEDIA_STREAM, QO_SELECT }, { URI_MEDIA_STREAM, QO_SKIP },
{ URI_MEDIA_STREAM, QO_SKIPTOKEN }, { URI_MEDIA_STREAM, QO_TOP }, { URI_MEDIA_STREAM, QO_APPLY },
{ URI_REFERENCES, QO_ID }, { URI_REFERENCES, QO_EXPAND }, { URI_REFERENCES, QO_SELECT },
{ URI_REFERENCES, QO_APPLY },
{ URI_REFERENCE, QO_FILTER }, { URI_REFERENCE, QO_ID }, { URI_REFERENCE, QO_EXPAND },
{ URI_REFERENCE, QO_COUNT }, { URI_REFERENCE, QO_ORDERBY }, { URI_REFERENCE, QO_SEARCH },
{ URI_REFERENCE, QO_SELECT }, { URI_REFERENCE, QO_SKIP }, { URI_REFERENCE, QO_SKIPTOKEN },
{ URI_REFERENCE, QO_TOP }, { URI_REFERENCE, QO_APPLY },
{ URI_PROPERTY_COMPLEX, QO_FILTER }, { URI_PROPERTY_COMPLEX, QO_ID }, { URI_PROPERTY_COMPLEX, QO_COUNT },
{ URI_PROPERTY_COMPLEX, QO_ORDERBY }, { URI_PROPERTY_COMPLEX, QO_SEARCH },
{ URI_PROPERTY_COMPLEX, QO_SKIP }, { URI_PROPERTY_COMPLEX, QO_SKIPTOKEN }, { URI_PROPERTY_COMPLEX, QO_TOP },
{ URI_PROPERTY_COMPLEX, QO_APPLY },
{ URI_PROPERTY_COMPLEX_COLLECTION, QO_ID }, { URI_PROPERTY_COMPLEX_COLLECTION, QO_SEARCH },
{ URI_PROPERTY_COMPLEX_COLLECTION_COUNT, QO_FORMAT },
{ URI_PROPERTY_COMPLEX_COLLECTION_COUNT, QO_ID }, { URI_PROPERTY_COMPLEX_COLLECTION_COUNT, QO_EXPAND },
{ URI_PROPERTY_COMPLEX_COLLECTION_COUNT, QO_COUNT }, { URI_PROPERTY_COMPLEX_COLLECTION_COUNT, QO_ORDERBY },
{ URI_PROPERTY_COMPLEX_COLLECTION_COUNT, QO_SEARCH }, { URI_PROPERTY_COMPLEX_COLLECTION_COUNT, QO_SELECT },
{ URI_PROPERTY_COMPLEX_COLLECTION_COUNT, QO_SKIP }, { URI_PROPERTY_COMPLEX_COLLECTION_COUNT, QO_SKIPTOKEN },
{ URI_PROPERTY_COMPLEX_COLLECTION_COUNT, QO_TOP },
{ URI_PROPERTY_PRIMITIVE, QO_FILTER }, { URI_PROPERTY_PRIMITIVE, QO_ID }, { URI_PROPERTY_PRIMITIVE, QO_EXPAND },
{ URI_PROPERTY_PRIMITIVE, QO_COUNT }, { URI_PROPERTY_PRIMITIVE, QO_ORDERBY },
{ URI_PROPERTY_PRIMITIVE, QO_SEARCH }, { URI_PROPERTY_PRIMITIVE, QO_SELECT },
{ URI_PROPERTY_PRIMITIVE, QO_SKIP }, { URI_PROPERTY_PRIMITIVE, QO_SKIPTOKEN },
{ URI_PROPERTY_PRIMITIVE, QO_TOP }, { URI_PROPERTY_PRIMITIVE, QO_APPLY },
{ URI_PROPERTY_PRIMITIVE_COLLECTION, QO_ID }, { URI_PROPERTY_PRIMITIVE_COLLECTION, QO_EXPAND },
{ URI_PROPERTY_PRIMITIVE_COLLECTION, QO_SEARCH }, { URI_PROPERTY_PRIMITIVE_COLLECTION, QO_SELECT },
{ URI_PROPERTY_PRIMITIVE_COLLECTION, QO_APPLY },
{ URI_PROPERTY_PRIMITIVE_COLLECTION_COUNT, QO_FORMAT },
{ URI_PROPERTY_PRIMITIVE_COLLECTION_COUNT, QO_ID }, { URI_PROPERTY_PRIMITIVE_COLLECTION_COUNT, QO_EXPAND },
{ URI_PROPERTY_PRIMITIVE_COLLECTION_COUNT, QO_COUNT },
{ URI_PROPERTY_PRIMITIVE_COLLECTION_COUNT, QO_ORDERBY }, { URI_PROPERTY_PRIMITIVE_COLLECTION_COUNT, QO_SEARCH },
{ URI_PROPERTY_PRIMITIVE_COLLECTION_COUNT, QO_SELECT }, { URI_PROPERTY_PRIMITIVE_COLLECTION_COUNT, QO_SKIP },
{ URI_PROPERTY_PRIMITIVE_COLLECTION_COUNT, QO_SKIPTOKEN }, { URI_PROPERTY_PRIMITIVE_COLLECTION_COUNT, QO_TOP },
{ URI_PROPERTY_PRIMITIVE_COLLECTION_COUNT, QO_APPLY },
{ URI_PROPERTY_PRIMITIVE_VALUE, QO_FILTER }, { URI_PROPERTY_PRIMITIVE_VALUE, QO_ID },
{ URI_PROPERTY_PRIMITIVE_VALUE, QO_EXPAND }, { URI_PROPERTY_PRIMITIVE_VALUE, QO_COUNT },
{ URI_PROPERTY_PRIMITIVE_VALUE, QO_ORDERBY }, { URI_PROPERTY_PRIMITIVE_VALUE, QO_SEARCH },
{ URI_PROPERTY_PRIMITIVE_VALUE, QO_SELECT }, { URI_PROPERTY_PRIMITIVE_VALUE, QO_SKIP },
{ URI_PROPERTY_PRIMITIVE_VALUE, QO_SKIPTOKEN }, { URI_PROPERTY_PRIMITIVE_VALUE, QO_TOP },
{ URI_PROPERTY_PRIMITIVE_VALUE, QO_APPLY },
{ URI_SINGLETON, QO_FILTER }, { URI_SINGLETON, QO_ID }, { URI_SINGLETON, QO_COUNT },
{ URI_SINGLETON, QO_ORDERBY }, { URI_SINGLETON, QO_SEARCH }, { URI_SINGLETON, QO_SKIP },
{ URI_SINGLETON, QO_SKIPTOKEN }, { URI_SINGLETON, QO_TOP }, { URI_SINGLETON, QO_APPLY },
{ URI_NAV_ENTITY, QO_FILTER }, { URI_NAV_ENTITY, QO_ID }, { URI_NAV_ENTITY, QO_COUNT },
{ URI_NAV_ENTITY, QO_ORDERBY }, { URI_NAV_ENTITY, QO_SEARCH }, { URI_NAV_ENTITY, QO_SKIP },
{ URI_NAV_ENTITY, QO_SKIPTOKEN }, { URI_NAV_ENTITY, QO_TOP }, { URI_NAV_ENTITY, QO_APPLY },
{ URI_NAV_ENTITY_SET, QO_ID },
{ URI_FI_ENTITY_SET, QO_ID },
{ URI_FI_ENTITY, QO_FILTER }, { URI_FI_ENTITY, QO_ID }, { URI_FI_ENTITY, QO_COUNT },
{ URI_FI_ENTITY, QO_ORDERBY }, { URI_FI_ENTITY, QO_SEARCH }, { URI_FI_ENTITY, QO_SKIP },
{ URI_FI_ENTITY, QO_SKIPTOKEN }, { URI_FI_ENTITY, QO_TOP },
{ URI_FI_ENTITY_SET_KEY, QO_FILTER }, { URI_FI_ENTITY_SET_KEY, QO_ID }, { URI_FI_ENTITY_SET_KEY, QO_COUNT },
{ URI_FI_ENTITY_SET_KEY, QO_ORDERBY }, { URI_FI_ENTITY_SET_KEY, QO_SEARCH },
{ URI_FI_ENTITY_SET_KEY, QO_SKIP }, { URI_FI_ENTITY_SET_KEY, QO_SKIPTOKEN }, { URI_FI_ENTITY_SET_KEY, QO_TOP },
{ URI_FI_ENTITY_SET_KEY, QO_APPLY }
};
private final String[][] actionWithValidSystemQueryOptions = {
// NoReturnType
{ URI_ACTION_NO_RETURN, QO_FORMAT },
// PrimReturnType
{ URI_ACTION_PRIM, QO_FORMAT },
// PrimCollectionReturnType
{ URI_ACTION_COLL_PRIM, QO_FILTER }, { URI_ACTION_COLL_PRIM, QO_FORMAT },
{ URI_ACTION_COLL_PRIM, QO_COUNT }, { URI_ACTION_COLL_PRIM, QO_ORDERBY },
{ URI_ACTION_COLL_PRIM, QO_SKIP }, { URI_ACTION_COLL_PRIM, QO_SKIPTOKEN },
{ URI_ACTION_COLL_PRIM, QO_TOP },
// ComplexReturnType
{ URI_ACTION_CT, QO_FORMAT }, { URI_ACTION_CT, QO_SELECT }, { URI_ACTION_CT, QO_EXPAND },
// ComplexCollectionReturnType
{ URI_ACTION_COLL_CT, QO_FILTER }, { URI_ACTION_COLL_CT, QO_FORMAT },
{ URI_ACTION_COLL_CT, QO_EXPAND }, { URI_ACTION_COLL_CT, QO_COUNT },
{ URI_ACTION_COLL_CT, QO_ORDERBY }, { URI_ACTION_COLL_CT, QO_SELECT },
{ URI_ACTION_COLL_CT, QO_SKIP }, { URI_ACTION_COLL_CT, QO_SKIPTOKEN },
{ URI_ACTION_COLL_CT, QO_TOP }, { URI_ACTION_COLL_CT, QO_APPLY },
// EntityReturnType
{ URI_ACTION_ENTITY, QO_FORMAT }, { URI_ACTION_ENTITY, QO_EXPAND }, { URI_ACTION_ENTITY, QO_SELECT },
// EntityCollectionReturnType
{ URI_ACTION_ES, QO_FORMAT }, { URI_ACTION_ES, QO_FILTER },
{ URI_ACTION_ES, QO_COUNT }, { URI_ACTION_ES, QO_ORDERBY }, { URI_ACTION_ES, QO_SEARCH },
{ URI_ACTION_ES, QO_SELECT }, { URI_ACTION_ES, QO_SKIP }, { URI_ACTION_ES, QO_SKIPTOKEN },
{ URI_ACTION_ES, QO_TOP }, { URI_ACTION_ES, QO_APPLY }
};
private final String[][] actionsWithNotValidSystemQueryOptions = {
// NoReturnType
{ URI_ACTION_NO_RETURN, QO_FILTER }, { URI_ACTION_NO_RETURN, QO_ID },
{ URI_ACTION_NO_RETURN, QO_EXPAND }, { URI_ACTION_NO_RETURN, QO_COUNT },
{ URI_ACTION_NO_RETURN, QO_ORDERBY }, { URI_ACTION_NO_RETURN, QO_SEARCH },
{ URI_ACTION_NO_RETURN, QO_SELECT }, { URI_ACTION_NO_RETURN, QO_SKIP },
{ URI_ACTION_NO_RETURN, QO_SKIPTOKEN }, { URI_ACTION_NO_RETURN, QO_TOP }, { URI_ACTION_NO_RETURN, QO_APPLY },
// PrimReturnType
{ URI_ACTION_PRIM, QO_FILTER }, { URI_ACTION_PRIM, QO_ID },
{ URI_ACTION_PRIM, QO_EXPAND }, { URI_ACTION_PRIM, QO_COUNT },
{ URI_ACTION_PRIM, QO_ORDERBY }, { URI_ACTION_PRIM, QO_SEARCH },
{ URI_ACTION_PRIM, QO_SELECT }, { URI_ACTION_PRIM, QO_SKIP },
{ URI_ACTION_PRIM, QO_SKIPTOKEN }, { URI_ACTION_PRIM, QO_TOP }, { URI_ACTION_PRIM, QO_APPLY },
// PrimCollectionReturnType
{ URI_ACTION_COLL_PRIM, QO_ID }, { URI_ACTION_COLL_PRIM, QO_EXPAND },
{ URI_ACTION_COLL_PRIM, QO_SEARCH }, { URI_ACTION_COLL_PRIM, QO_SELECT }, { URI_ACTION_COLL_PRIM, QO_APPLY },
// ComplexReturnType
{ URI_ACTION_CT, QO_FILTER }, { URI_ACTION_CT, QO_ID }, { URI_ACTION_CT, QO_COUNT },
{ URI_ACTION_CT, QO_ORDERBY }, { URI_ACTION_CT, QO_SEARCH },
{ URI_ACTION_CT, QO_SKIP }, { URI_ACTION_CT, QO_SKIPTOKEN }, { URI_ACTION_CT, QO_TOP },
{ URI_ACTION_CT, QO_APPLY },
// ComplexCollectionReturnType
{ URI_ACTION_COLL_CT, QO_ID }, { URI_ACTION_COLL_CT, QO_SEARCH },
// EntityReturnType
{ URI_ACTION_ENTITY, QO_FILTER }, { URI_ACTION_ENTITY, QO_ID }, { URI_ACTION_ENTITY, QO_COUNT },
{ URI_ACTION_ENTITY, QO_ORDERBY }, { URI_ACTION_ENTITY, QO_SEARCH },
{ URI_ACTION_ENTITY, QO_SKIP }, { URI_ACTION_ENTITY, QO_SKIPTOKEN }, { URI_ACTION_ENTITY, QO_TOP },
{ URI_ACTION_ENTITY, QO_APPLY },
// EntityCollectionReturnType
{ URI_ACTION_ES, QO_ID }
};
private static final OData odata = OData.newInstance();
private static final Edm edm = odata.createServiceMetadata(
new EdmTechProvider(), Collections.<EdmxReference> emptyList()).getEdm();
@Test
public void serviceDocumentMustNotFailForAllHttpMethods() throws Exception {
// We must not fail with a nullpointer here as the HTTP method to resource validation happens in the dispatcher.
for (final HttpMethod method : HttpMethod.values()) {
validate(URI_SERVICE, null, method);
}
}
@Test
public void validateForHttpMethods() throws Exception {
for (final HttpMethod method : HttpMethod.values()) {
validate(URI_ENTITY, null, method);
}
}
@Test
public void systemQueryOptionsNotAllowedForHttpPostDelete() throws Exception {
final String[] queryOptions =
{ QO_FILTER, QO_FORMAT, QO_EXPAND, QO_COUNT, QO_ORDERBY, QO_SEARCH, QO_SELECT, QO_SKIP, QO_TOP, QO_SKIPTOKEN };
for (int i = 0; i < queryOptions.length; i++) {
validateWrong(URI_ENTITY, queryOptions[i], HttpMethod.POST,
UriValidationException.MessageKeys.SYSTEM_QUERY_OPTION_NOT_ALLOWED_FOR_HTTP_METHOD);
validateWrong(URI_ENTITY, queryOptions[i], HttpMethod.DELETE,
UriValidationException.MessageKeys.SYSTEM_QUERY_OPTION_NOT_ALLOWED_FOR_HTTP_METHOD);
}
}
@Test
public void systemQueryOptionsExpandAndSelectAllowedForHttpPutAndPatch() throws Exception {
final String[] queryOptions =
{ QO_SELECT, QO_EXPAND };
for (int i = 0; i < queryOptions.length; i++) {
validate(URI_ENTITY, queryOptions[i], HttpMethod.PUT);
validate(URI_ENTITY, queryOptions[i], HttpMethod.PATCH);
}
}
@Test
public void systemQueryOptionsNotAllowedForHttpPutAndPatch() throws Exception {
final String[] queryOptions =
{ QO_FILTER, QO_FORMAT, QO_COUNT, QO_ORDERBY, QO_SEARCH, QO_SKIP, QO_TOP, QO_SKIPTOKEN };
for (int i = 0; i < queryOptions.length; i++) {
validateWrong(URI_ENTITY, queryOptions[i], HttpMethod.PUT,
UriValidationException.MessageKeys.SYSTEM_QUERY_OPTION_NOT_ALLOWED_FOR_HTTP_METHOD);
validateWrong(URI_ENTITY, queryOptions[i], HttpMethod.PATCH,
UriValidationException.MessageKeys.SYSTEM_QUERY_OPTION_NOT_ALLOWED_FOR_HTTP_METHOD);
}
}
@Test
public void systemQueryOptionIDAllowedForDELETEReferencesOnly() throws Exception {
validate(URI_REFERENCES, QO_ID, HttpMethod.DELETE);
validateWrong(URI_REFERENCES, QO_ID, HttpMethod.POST,
UriValidationException.MessageKeys.SYSTEM_QUERY_OPTION_NOT_ALLOWED_FOR_HTTP_METHOD);
validateWrong(URI_REFERENCES, QO_ID, HttpMethod.PUT,
UriValidationException.MessageKeys.SYSTEM_QUERY_OPTION_NOT_ALLOWED_FOR_HTTP_METHOD);
validateWrong(URI_REFERENCES, QO_ID, HttpMethod.PATCH,
UriValidationException.MessageKeys.SYSTEM_QUERY_OPTION_NOT_ALLOWED_FOR_HTTP_METHOD);
validateWrong(URI_ENTITY, QO_ID, HttpMethod.DELETE,
UriValidationException.MessageKeys.SYSTEM_QUERY_OPTION_NOT_ALLOWED_FOR_HTTP_METHOD);
}
@Test
public void checkKeys() throws Exception {
final TestUriValidator testUri = new TestUriValidator().setEdm(edm);
testUri.run("ESTwoKeyNav(PropertyInt16=1,PropertyString='abc')");
testUri.runEx("ESTwoKeyNav(xxx=1,yyy='abc')")
.isExValidation(UriValidationException.MessageKeys.INVALID_KEY_PROPERTY);
testUri.runEx("ESCollAllPrim(null)").isExValidation(UriValidationException.MessageKeys.INVALID_KEY_PROPERTY);
testUri.runEx("ESAllPrim(PropertyInt16='1')")
.isExSemantic(UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE);
testUri.runEx("ESAllPrim(12345678901234567890)")
.isExValidation(UriValidationException.MessageKeys.INVALID_KEY_PROPERTY);
testUri.runEx("ESTwoKeyNav(PropertyInt16=1,PropertyString=1)")
.isExSemantic(UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE);
testUri.runEx("ESTwoKeyNav(PropertyInt16=1,PropertyInt16=1)")
.isExValidation(UriValidationException.MessageKeys.DOUBLE_KEY_PROPERTY);
testUri.runEx("ESAllPrim(0)/NavPropertyETTwoPrimMany(xxx=42)")
.isExValidation(UriValidationException.MessageKeys.INVALID_KEY_PROPERTY);
testUri.runEx("ESAllPrim(0)/NavPropertyETTwoPrimMany(PropertyInt16='1')")
.isExSemantic(UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE);
}
@Test
public void checkValidSystemQueryOption() throws Exception {
for (final String[] uriArray : urisWithValidSystemQueryOptions) {
final String[] uri = constructUri(uriArray);
validate(uri[0], uri[1], HttpMethod.GET);
}
}
@Test
public void checkNonValidSystemQueryOption() throws Exception {
for (final String[] uriArray : urisWithNonValidSystemQueryOptions) {
final String[] uri = constructUri(uriArray);
validateWrong(uri[0], uri[1], HttpMethod.GET,
UriValidationException.MessageKeys.SYSTEM_QUERY_OPTION_NOT_ALLOWED);
}
}
@Test
public void validatePostOnActionSystemQueryOptions() throws Exception {
for (final String[] uriArray : actionWithValidSystemQueryOptions) {
final String[] uri = constructUri(uriArray);
validate(uri[0], uri[1], HttpMethod.POST);
}
}
@Test
public void checkPostOnActionSystemQueryOptionsNotValid() throws Exception {
for (final String[] uriArray : actionsWithNotValidSystemQueryOptions) {
final String[] uri = constructUri(uriArray);
validateWrong(uri[0], uri[1], HttpMethod.POST,
UriValidationException.MessageKeys.SYSTEM_QUERY_OPTION_NOT_ALLOWED);
}
}
@Test
public void propertyOperations() throws Exception {
validateWrong(URI_PROPERTY_PRIMITIVE_COLLECTION, null, HttpMethod.PATCH,
UriValidationException.MessageKeys.UNSUPPORTED_HTTP_METHOD);
validateWrong(URI_PROPERTY_COMPLEX_COLLECTION, null, HttpMethod.PATCH,
UriValidationException.MessageKeys.UNSUPPORTED_HTTP_METHOD);
validateWrong("ESKeyNav(1)/PropertyString", null, HttpMethod.DELETE,
UriValidationException.MessageKeys.UNSUPPORTED_HTTP_METHOD);
validateWrong("ESKeyNav(1)/PropertyString/$value", null, HttpMethod.DELETE,
UriValidationException.MessageKeys.UNSUPPORTED_HTTP_METHOD);
}
private String[] constructUri(final String[] uriParameterArray) {
final String path = uriParameterArray[0];
String query = "";
for (int i = 1; i < uriParameterArray.length; i++) {
if (i > 1) {
query += '&';
}
query += uriParameterArray[i];
}
return new String[] { path, query };
}
private void validate(final String path, final String query, final HttpMethod method) {
try {
new UriValidator().validate(new Parser(edm, odata).parseUri(path, query, null, null), method);
} catch (final UriParserException e) {
fail("Failed for " + method + " on URI: " + path + '?' + query);
} catch (final UriValidationException e) {
fail("Failed for " + method + " on URI: " + path + '?' + query);
}
}
private void validateWrong(final String path, final String query, final HttpMethod method,
final UriValidationException.MessageKeys expectedMessageKey) {
try {
new UriValidator().validate(new Parser(edm, odata).parseUri(path, query, null, null), method);
fail("Validation Exception not thrown: " + method + ' ' + path + '?' + query);
} catch (final UriParserException e) {
fail("Wrong Exception thrown: " + method + ' ' + path + '?' + query);
} catch (final UriValidationException e) {
assertEquals(expectedMessageKey, e.getMessageKey());
}
}
}