diff options
author | Jon Marius Venstad <venstad@gmail.com> | 2020-11-03 17:14:28 +0100 |
---|---|---|
committer | Jon Marius Venstad <venstad@gmail.com> | 2020-11-03 17:14:28 +0100 |
commit | 7a17516b491c1bb4a248b4cf7d3488fe93eabe34 (patch) | |
tree | fc82a314db40d93aa63ef5c46a5443193a43aaef /vespaclient-container-plugin/src/test/java | |
parent | c3c0c67621ec2ad422e69159fe46698e45e2cac1 (diff) |
Remove old /document/v1 handler
Diffstat (limited to 'vespaclient-container-plugin/src/test/java')
8 files changed, 0 insertions, 1307 deletions
diff --git a/vespaclient-container-plugin/src/test/java/com/yahoo/document/restapi/DocumentApiApplicationTest.java b/vespaclient-container-plugin/src/test/java/com/yahoo/document/restapi/DocumentApiApplicationTest.java deleted file mode 100644 index fd45a0d5dd7..00000000000 --- a/vespaclient-container-plugin/src/test/java/com/yahoo/document/restapi/DocumentApiApplicationTest.java +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.document.restapi; - -import com.yahoo.application.Application; -import com.yahoo.application.Networking; -import org.junit.Test; - -/** - * @author bratseth - */ -public class DocumentApiApplicationTest { - - /** Test that it is possible to instantiate an Application with a document-api */ - @Test - public void application_with_document_api() { - String services = - "<container version='1.0'>" + - " <http><server port=\"0\" id=\"foobar\"/></http>" + - " <document-api/>" + - "</container>"; - try (Application application = Application.fromServicesXml(services, Networking.enable)) { - } - } - -} diff --git a/vespaclient-container-plugin/src/test/java/com/yahoo/document/restapi/OperationHandlerImplTest.java b/vespaclient-container-plugin/src/test/java/com/yahoo/document/restapi/OperationHandlerImplTest.java deleted file mode 100644 index efb25f0e2b3..00000000000 --- a/vespaclient-container-plugin/src/test/java/com/yahoo/document/restapi/OperationHandlerImplTest.java +++ /dev/null @@ -1,445 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.document.restapi; - -import com.yahoo.document.fieldset.AllFields; -import com.yahoo.documentapi.DocumentAccess; -import com.yahoo.documentapi.ProgressToken; -import com.yahoo.documentapi.SyncParameters; -import com.yahoo.documentapi.VisitorControlHandler; -import com.yahoo.documentapi.VisitorParameters; -import com.yahoo.documentapi.VisitorSession; -import com.yahoo.documentapi.messagebus.MessageBusSyncSession; -import com.yahoo.messagebus.StaticThrottlePolicy; -import com.yahoo.metrics.simple.MetricReceiver; -import com.yahoo.vdslib.VisitorStatistics; -import com.yahoo.vespaclient.ClusterDef; -import org.junit.Test; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.net.URI; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.concurrent.atomic.AtomicReference; - -import static org.hamcrest.CoreMatchers.containsString; -import static org.hamcrest.CoreMatchers.instanceOf; -import static org.hamcrest.core.Is.is; -import static org.hamcrest.core.IsEqual.equalTo; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.fail; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - - -public class OperationHandlerImplTest { - - @Test(expected = IllegalArgumentException.class) - public void missingClusterDef() throws RestApiException { - List<ClusterDef> clusterDef = new ArrayList<>(); - OperationHandlerImpl.resolveClusterDef(Optional.empty(), clusterDef); - } - - @Test(expected = IllegalArgumentException.class) - public void missingClusterDefSpecifiedCluster() throws RestApiException { - List<ClusterDef> clusterDef = new ArrayList<>(); - OperationHandlerImpl.resolveClusterDef(Optional.of("cluster"), clusterDef); - } - - @Test(expected = RestApiException.class) - public void oneClusterPresentNotMatching() throws RestApiException { - List<ClusterDef> clusterDef = new ArrayList<>(); - clusterDef.add(new ClusterDef("foo", "configId")); - OperationHandlerImpl.resolveClusterDef(Optional.of("cluster"), clusterDef); - } - - private static String toRoute(ClusterDef clusterDef) { - return OperationHandlerImpl.clusterDefToRoute(clusterDef); - } - - @Test() - public void oneClusterMatching() throws RestApiException { - List<ClusterDef> clusterDef = new ArrayList<>(); - clusterDef.add(new ClusterDef("foo", "configId")); - assertThat(toRoute(OperationHandlerImpl.resolveClusterDef(Optional.of("foo"), clusterDef)), - is("[Storage:cluster=foo;clusterconfigid=configId]")); - } - - @Test() - public void oneClusterMatchingManyAvailable() throws RestApiException { - List<ClusterDef> clusterDef = new ArrayList<>(); - clusterDef.add(new ClusterDef("foo2", "configId2")); - clusterDef.add(new ClusterDef("foo", "configId")); - clusterDef.add(new ClusterDef("foo3", "configId2")); - assertThat(toRoute(OperationHandlerImpl.resolveClusterDef(Optional.of("foo"), clusterDef)), - is("[Storage:cluster=foo;clusterconfigid=configId]")); - } - - @Test() - public void unknown_target_cluster_throws_exception() throws RestApiException, IOException { - List<ClusterDef> clusterDef = new ArrayList<>(); - clusterDef.add(new ClusterDef("foo2", "configId2")); - clusterDef.add(new ClusterDef("foo", "configId")); - clusterDef.add(new ClusterDef("foo3", "configId2")); - try { - OperationHandlerImpl.resolveClusterDef(Optional.of("wrong"), clusterDef); - } catch(RestApiException e) { - assertThat(e.getResponse().getStatus(), is(400)); - String errorMsg = renderRestApiExceptionAsString(e); - assertThat(errorMsg, is("{\"errors\":[{\"description\":" + - "\"MISSING_CLUSTER Your vespa cluster contains the content clusters 'foo2', 'foo'," + - " 'foo3', not 'wrong'. Please select a valid vespa cluster.\",\"id\":-9}]}")); - return; - } - fail("Expected exception"); - } - - private String renderRestApiExceptionAsString(RestApiException e) throws IOException { - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - e.getResponse().render(stream); - return new String( stream.toByteArray()); - } - - private static class OperationHandlerImplFixture { - DocumentAccess documentAccess = mock(DocumentAccess.class); - AtomicReference<VisitorParameters> assignedParameters = new AtomicReference<>(); - VisitorControlHandler.CompletionCode completionCode = VisitorControlHandler.CompletionCode.SUCCESS; - int bucketsVisited = 0; - Map<String, String> bucketSpaces = new HashMap<>(); - MessageBusSyncSession mockSyncSession = mock(MessageBusSyncSession.class); // MBus session needed to avoid setRoute throwing. - - OperationHandlerImplFixture() { - bucketSpaces.put("foo", "global"); - bucketSpaces.put("document-type", "default"); - } - - OperationHandlerImpl createHandler() throws Exception { - VisitorSession visitorSession = mock(VisitorSession.class); - // Pre-bake an already completed session - when(documentAccess.createVisitorSession(any(VisitorParameters.class))).thenAnswer(p -> { - VisitorParameters params = (VisitorParameters)p.getArguments()[0]; - assignedParameters.set(params); - - VisitorStatistics statistics = new VisitorStatistics(); - statistics.setBucketsVisited(bucketsVisited); - params.getControlHandler().onVisitorStatistics(statistics); - - ProgressToken progress = new ProgressToken(); - params.getControlHandler().onProgress(progress); - - params.getControlHandler().onDone(completionCode, "bork bork"); - return visitorSession; - }); - when(documentAccess.createSyncSession(any(SyncParameters.class))).thenReturn(mockSyncSession); - OperationHandlerImpl.ClusterEnumerator clusterEnumerator = () -> Arrays.asList(new ClusterDef("foo", "configId")); - OperationHandlerImpl.BucketSpaceResolver bucketSpaceResolver = (clusterId, docType) -> Optional.ofNullable(bucketSpaces.get(docType)); - return new OperationHandlerImpl(documentAccess, clusterEnumerator, bucketSpaceResolver, MetricReceiver.nullImplementation); - } - } - - private static OperationHandler.VisitOptions.Builder optionsBuilder() { - return OperationHandler.VisitOptions.builder(); - } - - private static RestUri dummyVisitUri() throws Exception { - return new RestUri(new URI("http://localhost/document/v1/namespace/document-type/docid/")); - } - - private static RestUri apiRootVisitUri() throws Exception { - return new RestUri(new URI("http://localhost/document/v1/")); - } - - private static RestUri dummyGetUri() throws Exception { - return new RestUri(new URI("http://localhost/document/v1/namespace/document-type/docid/foo")); - } - - private static OperationHandler.VisitOptions visitOptionsWithWantedDocumentCount(int wantedDocumentCount) { - return optionsBuilder().wantedDocumentCount(wantedDocumentCount).build(); - } - - private static OperationHandler.VisitOptions emptyVisitOptions() { - return optionsBuilder().build(); - } - - @Test - public void timeout_without_buckets_visited_throws_timeout_error() throws Exception { - OperationHandlerImplFixture fixture = new OperationHandlerImplFixture(); - fixture.completionCode = VisitorControlHandler.CompletionCode.TIMEOUT; - fixture.bucketsVisited = 0; - // RestApiException hides its guts internally, so cannot trivially use @Rule directly to check for error category - try { - OperationHandlerImpl handler = fixture.createHandler(); - handler.visit(dummyVisitUri(), "", emptyVisitOptions()); - fail("Exception expected"); - } catch (RestApiException e) { - assertThat(e.getResponse().getStatus(), is(500)); - assertThat(renderRestApiExceptionAsString(e), containsString("Timed out")); - } - } - - @Test - public void timeout_with_buckets_visited_does_not_throw_timeout_error() throws Exception { - OperationHandlerImplFixture fixture = new OperationHandlerImplFixture(); - fixture.completionCode = VisitorControlHandler.CompletionCode.TIMEOUT; - fixture.bucketsVisited = 1; - - OperationHandlerImpl handler = fixture.createHandler(); - handler.visit(dummyVisitUri(), "", emptyVisitOptions()); - } - - @Test - public void handler_sets_default_visitor_session_timeout_parameter() throws Exception { - OperationHandlerImplFixture fixture = new OperationHandlerImplFixture(); - OperationHandlerImpl handler = fixture.createHandler(); - - handler.visit(dummyVisitUri(), "", emptyVisitOptions()); - - assertThat(fixture.assignedParameters.get().getSessionTimeoutMs(), is((long)OperationHandlerImpl.VISIT_TIMEOUT_MS)); - } - - private static VisitorParameters generatedVisitParametersFrom(RestUri restUri, String documentSelection, - OperationHandler.VisitOptions options) throws Exception { - OperationHandlerImplFixture fixture = new OperationHandlerImplFixture(); - OperationHandlerImpl handler = fixture.createHandler(); - - handler.visit(restUri, documentSelection, options); - return fixture.assignedParameters.get(); - } - - private static VisitorParameters generatedParametersFromVisitOptions(OperationHandler.VisitOptions options) throws Exception { - return generatedVisitParametersFrom(dummyVisitUri(), "", options); - } - - @Test - public void document_type_is_mapped_to_correct_bucket_space() throws Exception { - OperationHandlerImplFixture fixture = new OperationHandlerImplFixture(); - fixture.bucketSpaces.put("document-type", "langbein"); - OperationHandlerImpl handler = fixture.createHandler(); - handler.visit(dummyVisitUri(), "", emptyVisitOptions()); - - VisitorParameters parameters = fixture.assignedParameters.get(); - assertEquals("langbein", parameters.getBucketSpace()); - } - - @Test - public void unknown_bucket_space_mapping_throws_exception() throws Exception { - OperationHandlerImplFixture fixture = new OperationHandlerImplFixture(); - fixture.bucketSpaces.remove("document-type"); - try { - OperationHandlerImpl handler = fixture.createHandler(); - handler.visit(dummyVisitUri(), "", emptyVisitOptions()); - fail("Exception expected"); - } catch (RestApiException e) { - assertThat(e.getResponse().getStatus(), is(400)); - String errorMsg = renderRestApiExceptionAsString(e); - // FIXME isn't this really more of a case of unknown document type..? - assertThat(errorMsg, is("{\"errors\":[{\"description\":" + - "\"UNKNOWN_BUCKET_SPACE Document type 'document-type' in cluster 'foo' is not mapped to a known bucket space\",\"id\":-16}]}")); - } - } - - @Test - public void provided_wanted_document_count_is_propagated_to_visitor_parameters() throws Exception { - VisitorParameters params = generatedParametersFromVisitOptions(visitOptionsWithWantedDocumentCount(123)); - assertThat(params.getMaxTotalHits(), is((long)123)); - } - - @Test - public void wanted_document_count_is_1_unless_specified() throws Exception { - VisitorParameters params = generatedParametersFromVisitOptions(emptyVisitOptions()); - assertThat(params.getMaxTotalHits(), is((long)1)); - } - - @Test - public void too_low_wanted_document_count_is_bounded_to_1() throws Exception { - VisitorParameters params = generatedParametersFromVisitOptions(visitOptionsWithWantedDocumentCount(-1)); - assertThat(params.getMaxTotalHits(), is((long)1)); - - params = generatedParametersFromVisitOptions(visitOptionsWithWantedDocumentCount(Integer.MIN_VALUE)); - assertThat(params.getMaxTotalHits(), is((long)1)); - - params = generatedParametersFromVisitOptions(visitOptionsWithWantedDocumentCount(0)); - assertThat(params.getMaxTotalHits(), is((long)1)); - } - - @Test - public void too_high_wanted_document_count_is_bounded_to_upper_bound() throws Exception { - VisitorParameters params = generatedParametersFromVisitOptions(visitOptionsWithWantedDocumentCount(OperationHandlerImpl.WANTED_DOCUMENT_COUNT_UPPER_BOUND + 1)); - assertThat(params.getMaxTotalHits(), is((long)OperationHandlerImpl.WANTED_DOCUMENT_COUNT_UPPER_BOUND)); - - params = generatedParametersFromVisitOptions(visitOptionsWithWantedDocumentCount(Integer.MAX_VALUE)); - assertThat(params.getMaxTotalHits(), is((long)OperationHandlerImpl.WANTED_DOCUMENT_COUNT_UPPER_BOUND)); - } - - @Test - public void visit_field_set_covers_all_fields_by_default() throws Exception { - VisitorParameters params = generatedParametersFromVisitOptions(emptyVisitOptions()); - assertThat(params.fieldSet(), equalTo("document-type:[document]")); - } - - @Test - public void provided_visit_fieldset_is_propagated_to_visitor_parameters() throws Exception { - VisitorParameters params = generatedParametersFromVisitOptions(optionsBuilder().fieldSet("document-type:bjarne").build()); - assertThat(params.fieldSet(), equalTo("document-type:bjarne")); - } - - private void assertConcurrencyPropagated(VisitorParameters params, int expectedConcurrency) { - assertThat(params.getThrottlePolicy(), instanceOf(StaticThrottlePolicy.class)); - assertThat(((StaticThrottlePolicy)params.getThrottlePolicy()).getMaxPendingCount(), is(expectedConcurrency)); - } - - @Test - public void visit_concurrency_is_1_by_default() throws Exception { - VisitorParameters params = generatedParametersFromVisitOptions(emptyVisitOptions()); - assertConcurrencyPropagated(params, 1); - } - - @Test - public void visit_concurrency_is_propagated_to_visitor_parameters() throws Exception { - VisitorParameters params = generatedParametersFromVisitOptions(optionsBuilder().concurrency(3).build()); - assertConcurrencyPropagated(params, 3); - } - - @Test - public void too_low_visit_concurrency_is_capped_to_1() throws Exception { - VisitorParameters params = generatedParametersFromVisitOptions(optionsBuilder().concurrency(0).build()); - assertConcurrencyPropagated(params, 1); - } - - @Test - public void too_high_visit_concurrency_is_capped_to_max() throws Exception { - VisitorParameters params = generatedParametersFromVisitOptions( - optionsBuilder().concurrency(OperationHandlerImpl.CONCURRENCY_UPPER_BOUND + 1).build()); - assertConcurrencyPropagated(params, OperationHandlerImpl.CONCURRENCY_UPPER_BOUND); - } - - @Test - public void get_field_covers_all_fields_by_default() throws Exception { - OperationHandlerImplFixture fixture = new OperationHandlerImplFixture(); - OperationHandlerImpl handler = fixture.createHandler(); - handler.get(dummyGetUri(), Optional.empty()); - - verify(fixture.mockSyncSession).get(any(), eq("document-type:[document]"), any()); - } - - @Test - public void provided_get_fieldset_is_propagated_to_sync_session() throws Exception { - OperationHandlerImplFixture fixture = new OperationHandlerImplFixture(); - OperationHandlerImpl handler = fixture.createHandler(); - handler.get(dummyGetUri(), Optional.of("donald,duck")); - - verify(fixture.mockSyncSession).get(any(), eq("donald,duck"), any()); - } - - @Test - public void get_route_has_default_value_if_no_cluster_is_provided() throws Exception { - OperationHandlerImplFixture fixture = new OperationHandlerImplFixture(); - OperationHandlerImpl handler = fixture.createHandler(); - handler.get(dummyGetUri(), Optional.empty(), Optional.empty()); - - // TODO shouldn't this be default-get? - verify(fixture.mockSyncSession).setRoute(eq("default")); - } - - @Test - public void provided_get_cluster_is_propagated_as_route_to_sync_session() throws Exception { - OperationHandlerImplFixture fixture = new OperationHandlerImplFixture(); - OperationHandlerImpl handler = fixture.createHandler(); - handler.get(dummyGetUri(), Optional.empty(), Optional.of("foo")); - - verify(fixture.mockSyncSession).setRoute(eq("[Storage:cluster=foo;clusterconfigid=configId]")); - } - - @Test - public void api_root_visit_uri_requires_cluster_set() throws Exception { - OperationHandlerImplFixture fixture = new OperationHandlerImplFixture(); - OperationHandlerImpl handler = fixture.createHandler(); - try { - handler.visit(apiRootVisitUri(), "", emptyVisitOptions()); - fail("Exception expected"); - } catch (RestApiException e) { - assertThat(e.getResponse().getStatus(), is(400)); - assertThat(renderRestApiExceptionAsString(e), containsString( - "MISSING_CLUSTER Must set 'cluster' parameter to a valid content cluster id " + - "when visiting at a root /document/v1/ level")); - } - } - - @Test - public void api_root_visiting_propagates_request_route() throws Exception { - VisitorParameters parameters = generatedVisitParametersFrom(apiRootVisitUri(), "", optionsBuilder().cluster("foo").build()); - assertEquals("[Storage:cluster=foo;clusterconfigid=configId]", parameters.getRoute().toString()); - } - - @Test - public void api_root_visiting_targets_default_bucket_space_by_default() throws Exception { - VisitorParameters parameters = generatedVisitParametersFrom(apiRootVisitUri(), "", optionsBuilder().cluster("foo").build()); - assertEquals("default", parameters.getBucketSpace()); - } - - @Test - public void api_root_visiting_can_explicitly_specify_bucket_space() throws Exception { - VisitorParameters parameters = generatedVisitParametersFrom(apiRootVisitUri(), "", - optionsBuilder().cluster("foo").bucketSpace("global").build()); - assertEquals("global", parameters.getBucketSpace()); - } - - @Test - public void api_root_visiting_throws_exception_on_unknown_bucket_space_name() throws Exception { - try { - generatedVisitParametersFrom(apiRootVisitUri(), "", optionsBuilder().cluster("foo").bucketSpace("langbein").build()); - } catch (RestApiException e) { - assertThat(e.getResponse().getStatus(), is(400)); - assertThat(renderRestApiExceptionAsString(e), containsString( - "UNKNOWN_BUCKET_SPACE Bucket space 'langbein' is not a known bucket space " + - "(expected 'default' or 'global')")); - } - } - - @Test - public void api_root_visiting_has_empty_document_selection_by_default() throws Exception { - VisitorParameters parameters = generatedVisitParametersFrom(apiRootVisitUri(), "", optionsBuilder().cluster("foo").build()); - assertEquals("", parameters.getDocumentSelection()); - } - - @Test - public void api_root_visiting_propagates_provided_document_selection() throws Exception { - VisitorParameters parameters = generatedVisitParametersFrom(apiRootVisitUri(), "baz.blarg", optionsBuilder().cluster("foo").build()); - // Note: syntax correctness of selection is checked and enforced by RestApi - assertEquals("baz.blarg", parameters.getDocumentSelection()); - } - - @Test - public void api_root_visiting_uses_all_fieldset_by_default() throws Exception { - VisitorParameters parameters = generatedVisitParametersFrom(apiRootVisitUri(), "", optionsBuilder().cluster("foo").build()); - assertEquals(AllFields.NAME, parameters.getFieldSet()); - } - - @Test - public void api_root_visiting_propagates_provided_fieldset() throws Exception { - VisitorParameters parameters = generatedVisitParametersFrom(apiRootVisitUri(), "", - optionsBuilder().cluster("foo").fieldSet("zoidberg:[document]").build()); - assertEquals("zoidberg:[document]", parameters.getFieldSet()); - } - - @Test - public void namespace_and_doctype_augmented_selection_has_parenthesized_selection_sub_expression() throws Exception { - VisitorParameters parameters = generatedVisitParametersFrom(dummyVisitUri(), "1 != 2", optionsBuilder().cluster("foo").build()); - assertEquals("((1 != 2) and document-type and (id.namespace=='namespace'))", parameters.getDocumentSelection()); - } - - @Test - public void namespace_and_doctype_visit_without_selection_does_not_contain_selection_sub_expression() throws Exception { - VisitorParameters parameters = generatedVisitParametersFrom(dummyVisitUri(), "", optionsBuilder().cluster("foo").build()); - assertEquals("document-type and (id.namespace=='namespace')", parameters.getDocumentSelection()); - } - -} diff --git a/vespaclient-container-plugin/src/test/java/com/yahoo/document/restapi/RestUriTest.java b/vespaclient-container-plugin/src/test/java/com/yahoo/document/restapi/RestUriTest.java deleted file mode 100644 index bdeee12a32a..00000000000 --- a/vespaclient-container-plugin/src/test/java/com/yahoo/document/restapi/RestUriTest.java +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.document.restapi; - -import org.apache.http.client.utils.URIBuilder; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; -import java.util.Optional; - -import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; - -public class RestUriTest { - - URI createUri(String path, String query) throws URISyntaxException { - return new URIBuilder() - .addParameter("foo", "bar") - .setHost("host") - .setScheme("http") - .setPort(666) - .setPath(path) - .setCustomQuery(query) - .setFragment("fargment").build(); - } - - @Rule - public ExpectedException thrown= ExpectedException.none(); - - @Test - public void testBasic() throws Exception { - RestUri restUri = new RestUri(createUri("/document/v1/namespace/doctype/docid/myid", "query")); - assertThat(restUri.getDocId(), is("myid")); - assertThat(restUri.getDocumentType(), is("doctype")); - assertThat(restUri.getNamespace(), is("namespace")); - assertThat(restUri.getGroup(), is(Optional.<RestUri.Group>empty())); - assertThat(restUri.generateFullId(), is("id:namespace:doctype::myid")); - } - - @Test - public void encodingSlashes() throws Exception { - // Try with slashes encoded. - final String id = " !\"øæåp/:;&,.:;'1Q"; - String encodedId = URLEncoder.encode(id, StandardCharsets.UTF_8.name()); - RestUri restUri = new RestUri(URI.create("/document/v1/namespace/doctype/docid/" + encodedId)); - assertThat(restUri.getDocId(), is(id)); - assertThat(restUri.getDocumentType(), is("doctype")); - assertThat(restUri.getNamespace(), is("namespace")); - assertThat(restUri.getGroup(), is(Optional.<RestUri.Group>empty())); - assertThat(restUri.generateFullId(), is("id:namespace:doctype::" + id)); - } - - @Test - public void encodingSlashes2() throws Exception { - // This will decode the slashes. - final String id = " !\"øæåp/:;&,.:;'1Q "; - RestUri restUri = new RestUri(createUri("/document/v1/namespace/doctype/docid/" + id, "query")); - assertThat(restUri.getDocId(), is(id)); - assertThat(restUri.getDocumentType(), is("doctype")); - assertThat(restUri.getNamespace(), is("namespace")); - assertThat(restUri.getGroup(), is(Optional.<RestUri.Group>empty())); - assertThat(restUri.generateFullId(), is("id:namespace:doctype::" + id)); - } - - - @Test - public void testVisit() throws Exception { - RestUri restUri = new RestUri(createUri("/document/v1/namespace/doctype/docid/", "query")); - assertThat(restUri.getDocId(), is("")); - assertThat(restUri.getDocumentType(), is("doctype")); - assertThat(restUri.getNamespace(), is("namespace")); - assertThat(restUri.getGroup(), is(Optional.<RestUri.Group>empty())); - assertThat(restUri.generateFullId(), is("id:namespace:doctype::")); - } - - @Test - public void testOneSlashTooMuchWhichIsFine() throws Exception { - RestUri restUri = new RestUri(createUri("/document/v1/namespace/doctype/docid/myid:342:23/wrong", "")); - assertThat(restUri.getDocId(), is("myid:342:23/wrong")); - } - - @Test - public void testGroupG() throws Exception { - RestUri restUri = new RestUri(createUri("/document/v1/namespace/doctype/group/group/myid", "")); - assertThat(restUri.getDocId(), is("myid")); - assertThat(restUri.getDocumentType(), is("doctype")); - assertThat(restUri.getGroup().get().name, is('g')); - assertThat(restUri.getGroup().get().value, is("group")); - assertThat(restUri.generateFullId(), is("id:namespace:doctype:g=group:myid")); - } - - @Test - public void testGroupUrlDecode() throws Exception { - RestUri restUri = new RestUri(createUri("/document/v1/namespace/doctype/group/group#123/myid", "")); - assertThat(restUri.getDocId(), is("myid")); - assertThat(restUri.getDocumentType(), is("doctype")); - assertThat(restUri.getGroup().get().name, is('g')); - assertThat(restUri.getGroup().get().value, is("group#123")); - assertThat(restUri.generateFullId(), is("id:namespace:doctype:g=group#123:myid")); - } - - @Test - public void testGroupN() throws Exception { - RestUri restUri = new RestUri(createUri("/document/v1/namespace/doctype/number/group/myid", "")); - assertThat(restUri.getGroup().get().name, is('n')); - assertThat(restUri.getGroup().get().value, is("group")); - } - - @Test - public void testGroupUnknown() throws Exception { - thrown.expect(RestApiException.class); - new RestUri(createUri("/document/v1/namespace/doctype/Q/myid", "")); - } - - @Test - public void testDocIdAsIs() throws Exception { - RestUri restUri = new RestUri(new URI("/document/v1/test/newsarticle/docid/http%3a%2f%2fvn.news.yahoo.com%2fgi-th-ng-t-n-ng-khoa-h-205000458.html").normalize()); - assertThat(restUri.getNamespace(), is("test")); - assertThat(restUri.getDocumentType(), is("newsarticle")); - assertThat(restUri.getDocId(), is("http://vn.news.yahoo.com/gi-th-ng-t-n-ng-khoa-h-205000458.html")); - assertThat(restUri.generateFullId(), is("id:test:newsarticle::http://vn.news.yahoo.com/gi-th-ng-t-n-ng-khoa-h-205000458.html")); - } - -} diff --git a/vespaclient-container-plugin/src/test/java/com/yahoo/document/restapi/feed-document1.json b/vespaclient-container-plugin/src/test/java/com/yahoo/document/restapi/feed-document1.json deleted file mode 100644 index e69de29bb2d..00000000000 --- a/vespaclient-container-plugin/src/test/java/com/yahoo/document/restapi/feed-document1.json +++ /dev/null diff --git a/vespaclient-container-plugin/src/test/java/com/yahoo/document/restapi/resource/MockedOperationHandler.java b/vespaclient-container-plugin/src/test/java/com/yahoo/document/restapi/resource/MockedOperationHandler.java deleted file mode 100644 index eb6bb609970..00000000000 --- a/vespaclient-container-plugin/src/test/java/com/yahoo/document/restapi/resource/MockedOperationHandler.java +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.document.restapi.resource; - -import com.yahoo.document.restapi.OperationHandler; -import com.yahoo.document.restapi.Response; -import com.yahoo.document.restapi.RestApiException; -import com.yahoo.document.restapi.RestUri; -import com.yahoo.vespaxmlparser.FeedOperation; - -import java.util.Optional; - -/** - * Mock that collects info about operation and returns them on second delete. - */ -public class MockedOperationHandler implements OperationHandler { - - StringBuilder log = new StringBuilder(); - int deleteCount = 0; - - @Override - public VisitResult visit(RestUri restUri, String documentSelection, VisitOptions options) throws RestApiException { - return new VisitResult(Optional.of("token"), "List of json docs, cont token " - + options.continuation.orElse("not set") + ", doc selection: '" - + documentSelection + "'" - + options.wantedDocumentCount.map(n -> String.format(", min docs returned: %d", n)).orElse("") - + options.fieldSet.map(s -> String.format(", field set: '%s'", s)).orElse("") - + options.concurrency.map(n -> String.format(", concurrency: %d", n)).orElse("") - + options.bucketSpace.map(s -> String.format(", bucket space: '%s'", s)).orElse("") - + options.cluster.map(s -> String.format(", cluster: '%s'", s)).orElse("")); - } - - @Override - @SuppressWarnings("deprecation") - public void put(RestUri restUri, FeedOperation data, Optional<String> route) throws RestApiException { - log.append("PUT: " + data.getDocument().getId()); - log.append(data.getDocument().getHeader().toString()); - } - - @Override - public void update(RestUri restUri, FeedOperation data, Optional<String> route) throws RestApiException { - log.append("UPDATE: " + data.getDocumentUpdate().getId()); - log.append(data.getDocumentUpdate().fieldUpdates().toString()); - if (data.getDocumentUpdate().getCreateIfNonExistent()) { - log.append("[CREATE IF NON EXISTENT IS TRUE]"); - } - } - - @Override - public void delete(RestUri restUri, String condition, Optional<String> route) throws RestApiException { - deleteCount++; - if (deleteCount == 2) { - String theLog = log.toString(); - log = new StringBuilder(); - deleteCount = 0; - throw new RestApiException(Response.createErrorResponse(666, theLog, RestUri.apiErrorCodes.ERROR_ID_BASIC_USAGE)); - } - log.append("DELETE: " + restUri.generateFullId()); - } - - @Override - public Optional<String> get(RestUri restUri, Optional<String> fieldSet, Optional<String> cluster) throws RestApiException { - log.append("GET: " + restUri.generateFullId()); - // This is _not_ an elegant way to return data back to the test. - // An alternative is removing this entire class in favor of explicit mock expectations. - if (!fieldSet.isPresent() && !cluster.isPresent()) { - return Optional.empty(); - } - return Optional.of(String.format("{\"fields\": {\"fieldset\": \"%s\",\"cluster\":\"%s\"}}", - fieldSet.orElse(""), cluster.orElse(""))); - } - - @Override - public Optional<String> get(RestUri restUri, Optional<String> fieldSet) throws RestApiException { - return get(restUri, fieldSet, Optional.empty()); - } - - @Override - public Optional<String> get(RestUri restUri) throws RestApiException { - return get(restUri, Optional.empty()); - } - -} diff --git a/vespaclient-container-plugin/src/test/java/com/yahoo/document/restapi/resource/RestApiMaxThreadTest.java b/vespaclient-container-plugin/src/test/java/com/yahoo/document/restapi/resource/RestApiMaxThreadTest.java deleted file mode 100644 index 39d5617dd4f..00000000000 --- a/vespaclient-container-plugin/src/test/java/com/yahoo/document/restapi/resource/RestApiMaxThreadTest.java +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.document.restapi.resource; - -import com.yahoo.container.jdisc.HttpRequest; -import com.yahoo.container.jdisc.HttpResponse; -import com.yahoo.document.restapi.OperationHandler; -import org.junit.Test; - -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Executor; -import java.util.concurrent.atomic.AtomicInteger; - -import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; -import static org.mockito.Mockito.mock; - -public class RestApiMaxThreadTest { - final CountDownLatch latch = new CountDownLatch(1); - final AtomicInteger requestsInFlight = new AtomicInteger(0); - private class RestApiMocked extends RestApi { - - public RestApiMocked() { - super(mock(Executor.class), null, (OperationHandler)null, 20); - } - - @Override - protected HttpResponse handleInternal(HttpRequest request) { - requestsInFlight.incrementAndGet(); - try { - latch.await(); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - return null; - } - } - - @Test - public void testCallsAreThrottled() throws InterruptedException { - RestApiMocked restApiMocked = new RestApiMocked(); - // Fire lots of requests. - for (int x = 0; x < 30; x++) { - new Thread(() -> restApiMocked.handle(null)).start(); - } - // Wait for all threads to be used - while (requestsInFlight.get() != 19) { - Thread.sleep(1); - } - // A new request should be blocked. - final HttpResponse response = restApiMocked.handle(null); - assertThat(response.getStatus(), is(429)); - latch.countDown(); - } -} diff --git a/vespaclient-container-plugin/src/test/java/com/yahoo/document/restapi/resource/RestApiTest.java b/vespaclient-container-plugin/src/test/java/com/yahoo/document/restapi/resource/RestApiTest.java deleted file mode 100644 index 0661363477f..00000000000 --- a/vespaclient-container-plugin/src/test/java/com/yahoo/document/restapi/resource/RestApiTest.java +++ /dev/null @@ -1,537 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.document.restapi.resource; - -import com.yahoo.application.Application; -import com.yahoo.application.Networking; -import com.yahoo.application.container.handler.Request; -import com.yahoo.container.Container; -import com.yahoo.jdisc.http.server.jetty.JettyHttpServer; -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.client.HttpClient; -import org.apache.http.client.methods.HttpDelete; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.client.methods.HttpPut; -import org.apache.http.client.methods.HttpRequestBase; -import org.apache.http.entity.ContentType; -import org.apache.http.entity.StringEntity; -import org.apache.http.impl.client.HttpClientBuilder; -import org.apache.http.util.EntityUtils; -import org.junit.After; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; - -import java.io.IOException; -import java.io.UncheckedIOException; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; -import java.nio.file.Paths; -import java.util.function.Function; - -import static org.hamcrest.core.Is.is; -import static org.hamcrest.core.IsNot.not; -import static org.hamcrest.core.StringContains.containsString; -import static org.hamcrest.core.StringStartsWith.startsWith; -import static org.junit.Assert.assertThat; - -public class RestApiTest { - - Application application; - - @Before - public void setup() throws Exception { - application = Application.fromApplicationPackage(Paths.get("src/test/rest-api-application"), Networking.enable); - } - - @After - public void tearDown() throws Exception { - application.close(); - } - - private static class Response { - final int code; - final String body; - - Response(int code, String body) { - this.code = code; - this.body = body; - } - } - - String post_test_uri = "/document/v1/namespace/testdocument/docid/c"; - String post_test_doc = "{\n" + - "\"foo\" : \"bar\"," + - "\"fields\": {\n" + - "\"title\": \"This is the title\",\n" + - "\"body\": \"This is the body\"" + - "}" + - "}"; - String post_test_response = "{\"id\":\"id:namespace:testdocument::c\"," + - "\"pathId\":\"/document/v1/namespace/testdocument/docid/c\"}"; - - // Run this test to manually do request against the REST-API with backend mock. - @Ignore - @Test - public void blockingTest() throws Exception { - System.out.println("Running on port " + getFirstListenPort()); - Thread.sleep(Integer.MAX_VALUE); - } - - @Test - public void testbasicPost() throws Exception { - Request request = new Request("http://localhost:" + getFirstListenPort() + post_test_uri); - HttpPost httpPost = new HttpPost(request.getUri()); - StringEntity entity = new StringEntity(post_test_doc, ContentType.create("application/json")); - httpPost.setEntity(entity); - Response response = doRest(httpPost); - assertThat(response.code, is(200)); - assertThat(response.body, is(post_test_response)); - } - - String post_test_uri_cond = "/document/v1/namespace/testdocument/docid/c?condition=foo"; - String post_test_doc_cond = "{\n" + - "\"foo\" : \"bar\"," + - "\"fields\": {\n" + - "\"title\": \"This is the title\",\n" + - "\"body\": \"This is the body\"" + - "}" + - "}"; - String post_test_response_cond = "{\"id\":\"id:namespace:testdocument::c\"," + - "\"pathId\":\"/document/v1/namespace/testdocument/docid/c\"}"; - - @Test - public void testConditionalPost() throws Exception { - Request request = new Request("http://localhost:" + getFirstListenPort() + post_test_uri_cond); - HttpPost httpPost = new HttpPost(request.getUri()); - StringEntity entity = new StringEntity(post_test_doc_cond, ContentType.create("application/json")); - httpPost.setEntity(entity); - Response response = doRest(httpPost); - assertThat(response.code, is(200)); - assertThat(response.body, is(post_test_response_cond)); - } - - @Test - public void testEmptyPost() throws Exception { - Request request = new Request("http://localhost:" + getFirstListenPort() + post_test_uri); - HttpPost httpPost = new HttpPost(request.getUri()); - StringEntity entity = new StringEntity("", ContentType.create("application/json")); - httpPost.setEntity(entity); - assertHttp400ResponseContains(doRest(httpPost), "Could not read document, no document?"); - } - - String update_test_uri = "/document/v1/namespace/testdocument/docid/c"; - String update_test_doc = "{\n" + - "\t\"fields\": {\n" + - "\"title\": {\n" + - "\"assign\": \"Oh lala\"\n" + - "}\n" + - "}\n" + - "}\n"; - - String update_test_response = "{\"id\":\"id:namespace:testdocument::c\"," + - "\"pathId\":\"/document/v1/namespace/testdocument/docid/c\"}"; - - @Test - public void testbasicUpdate() throws Exception { - Request request = new Request("http://localhost:" + getFirstListenPort() + update_test_uri); - HttpPut httpPut = new HttpPut(request.getUri()); - StringEntity entity = new StringEntity(update_test_doc, ContentType.create("application/json")); - httpPut.setEntity(entity); - Response response = doRest(httpPut); - assertThat(response.code, is(200)); - assertThat(response.body, is(update_test_response)); - assertThat(getLog(), not(containsString("CREATE IF NON EXISTING IS TRUE"))); - } - - @Test - public void testbasicUpdateCreateTrue() throws Exception { - Request request = new Request("http://localhost:" + getFirstListenPort() + update_test_uri + "?create=true"); - HttpPut httpPut = new HttpPut(request.getUri()); - StringEntity entity = new StringEntity(update_test_doc, ContentType.create("application/json")); - httpPut.setEntity(entity); - Response response = doRest(httpPut); - assertThat(response.code, is(200)); - assertThat(response.body, is(update_test_response)); - assertThat(getLog(), containsString("CREATE IF NON EXISTENT IS TRUE")); - } - - String update_test_create_if_non_existient_uri = "/document/v1/namespace/testdocument/docid/c"; - String update_test_create_if_non_existient_doc = "{\n" + - "\"create\":true," + - "\t\"fields\": {\n" + - "\"title\": {\n" + - "\"assign\": \"Oh lala\"\n" + - "}\n" + - "}\n" + - "}\n"; - - String update_test_create_if_non_existing_response = "{\"id\":\"id:namespace:testdocument::c\"," + - "\"pathId\":\"/document/v1/namespace/testdocument/docid/c\"}"; - - @Test - public void testCreateIfNonExistingUpdateInDocTrue() throws Exception { - Request request = new Request("http://localhost:" + getFirstListenPort() + update_test_create_if_non_existient_uri); - HttpPut httpPut = new HttpPut(request.getUri()); - StringEntity entity = new StringEntity(update_test_create_if_non_existient_doc, ContentType.create("application/json")); - httpPut.setEntity(entity); - assertThat(doRest(httpPut).body, is(update_test_create_if_non_existing_response)); - assertThat(getLog(), containsString("CREATE IF NON EXISTENT IS TRUE")); - } - - @Test - public void testCreateIfNonExistingUpdateInDocTrueButQueryParamsFalse() throws Exception { - Request request = new Request("http://localhost:" + getFirstListenPort() + update_test_create_if_non_existient_uri + "?create=false"); - HttpPut httpPut = new HttpPut(request.getUri()); - StringEntity entity = new StringEntity(update_test_create_if_non_existient_doc, ContentType.create("application/json")); - httpPut.setEntity(entity); - assertThat(doRest(httpPut).body, is(update_test_create_if_non_existing_response)); - assertThat(getLog(), not(containsString("CREATE IF NON EXISTENT IS TRUE"))); - } - - @Test - public void bogus_create_parameter_value_returns_http_400_error() throws Exception { - Request request = new Request("http://localhost:" + getFirstListenPort() + update_test_uri + "?create=batman"); - HttpPut httpPut = new HttpPut(request.getUri()); - StringEntity entity = new StringEntity(update_test_doc, ContentType.create("application/json")); - httpPut.setEntity(entity); - assertHttp400ResponseContains(doRest(httpPut), "Invalid value for 'create' parameter: Must be empty, true, or false but was 'batman'"); - } - - // Get logs through some hackish fetch method. Logs is something the mocked backend write. - String getLog() throws IOException { - // The mocked backend will throw a runtime exception with a log if delete is called three times.. - Request request = new Request("http://localhost:" + getFirstListenPort() + remove_test_uri); - HttpDelete delete = new HttpDelete(request.getUri()); - doRest(delete); - return doRest(delete).body; - } - - - String remove_test_uri = "/document/v1/namespace/testdocument/docid/c"; - String remove_test_response = "{\"id\":\"id:namespace:testdocument::c\"," + - "\"pathId\":\"/document/v1/namespace/testdocument/docid/c\"}"; - - @Test - public void testbasicRemove() throws Exception { - Request request = new Request("http://localhost:" + getFirstListenPort() + remove_test_uri); - HttpDelete delete = new HttpDelete(request.getUri()); - Response response = doRest(delete); - assertThat(response.code, is(200)); - assertThat(response.body, is(remove_test_response)); - } - - String get_test_uri = "/document/v1/namespace/document-type/docid/c"; - String get_response_part1 = "\"pathId\":\"/document/v1/namespace/document-type/docid/c\""; - String get_response_part2 = "\"id\":\"id:namespace:document-type::c\""; - - - @Test - public void testbasicGet() throws Exception { - Request request = new Request("http://localhost:" + getFirstListenPort() + get_test_uri); - HttpGet get = new HttpGet(request.getUri()); - Response response = doRest(get); - assertThat(response.code, is(404)); // Mock returns Not Found - assertThat(response.body, containsString(get_response_part1)); - assertThat(response.body, containsString(get_response_part2)); - } - - String id_test_uri = "/document/v1/namespace/document-type/docid/f/u/n/n/y/!"; - String id_response_part1 = "\"pathId\":\"/document/v1/namespace/document-type/docid/f/u/n/n/y/!\""; - String id_response_part2 = "\"id\":\"id:namespace:document-type::f/u/n/n/y/!\""; - - @Test - public void testSlashesInId() throws Exception { - Request request = new Request("http://localhost:" + getFirstListenPort() + id_test_uri); - HttpGet get = new HttpGet(request.getUri()); - Response response = doRest(get); - assertThat(response.code, is(404)); // Mock returns Not Found - assertThat(response.body, containsString(id_response_part1)); - assertThat(response.body, containsString(id_response_part2)); - } - - - String get_enc_id = "!\":æøå@/& Q1+"; - // Space encoded as %20, not encoding ! - String get_enc_id_encoded_v1 = "!%22%3A%C3%A6%C3%B8%C3%A5%40%2F%26%20Q1%2B"; - // Space encoded as + - String get_enc_id_encoded_v2 = "%21%22%3A%C3%A6%C3%B8%C3%A5%40%2F%26+Q1%2B"; - String get_enc_test_uri_v1 = "/document/v1/namespace/document-type/docid/" + get_enc_id_encoded_v1; - String get_enc_test_uri_v2 = "/document/v1/namespace/document-type/docid/" + get_enc_id_encoded_v2; - String get_enc_response_part1 = "\"pathId\":\"/document/v1/namespace/document-type/docid/" + get_enc_id_encoded_v1 + "\""; - String get_enc_response_part1_v2 = "\"pathId\":\"/document/v1/namespace/document-type/docid/" + get_enc_id_encoded_v2 + "\""; - - // JSON encode " as \" - String get_enc_response_part2 = "\"id\":\"id:namespace:document-type::" + get_enc_id.replace("\"", "\\\"") + "\""; - - - @Test - public void testbasicEncodingV1() throws Exception { - Request request = new Request("http://localhost:" + getFirstListenPort() + get_enc_test_uri_v1); - HttpGet get = new HttpGet(request.getUri()); - Response response = doRest(get); - assertThat(response.code, is(404)); // Mock returns Not Found - assertThat(response.body, containsString(get_enc_response_part1)); - assertThat(response.body, containsString(get_enc_response_part2)); - } - - @Test - public void testbasicEncodingV2() throws Exception { - Request request = new Request("http://localhost:" + getFirstListenPort() + get_enc_test_uri_v2); - HttpGet get = new HttpGet(request.getUri()); - Response response = doRest(get); - assertThat(response.code, is(404)); // Mock returns Not Found - assertThat(response.body, containsString(get_enc_response_part1_v2)); - assertThat(response.body, containsString(get_enc_response_part2)); - } - - @Test - public void get_fieldset_parameter_is_propagated() { - Request request = new Request(String.format("http://localhost:%s/document/v1/namespace/document-type/docid/bar?fieldSet=foo,baz", getFirstListenPort())); - HttpGet get = new HttpGet(request.getUri()); - assertHttp200ResponseContains(doRest(get), "\"fieldset\":\"foo,baz\""); - } - - @Test - public void get_cluster_parameter_is_propagated() { - Request request = new Request(String.format("http://localhost:%s/document/v1/namespace/document-type/docid/bar?cluster=my_cool_cluster", getFirstListenPort())); - HttpGet get = new HttpGet(request.getUri()); - assertHttp200ResponseContains(doRest(get), "\"cluster\":\"my_cool_cluster\""); - } - - String visit_test_uri = "/document/v1/namespace/document-type/docid/?continuation=abc"; - String visit_response_part1 = "\"documents\":[List of json docs, cont token abc, doc selection: '']"; - String visit_response_part2 = "\"continuation\":\"token\""; - String visit_response_part3 = "\"pathId\":\"/document/v1/namespace/document-type/docid/\""; - - @Test - public void testbasicVisit() throws Exception { - Request request = new Request("http://localhost:" + getFirstListenPort() + visit_test_uri); - HttpGet get = new HttpGet(request.getUri()); - Response response = doRest(get); - assertThat(response.code, is(200)); - assertThat(response.body, containsString(visit_response_part1)); - assertThat(response.body, containsString(visit_response_part2)); - assertThat(response.body, containsString(visit_response_part3)); - } - - private static String encoded(String original) { - try { - return URLEncoder.encode(original, StandardCharsets.UTF_8.name()); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); - } - } - - private static String defaultPathPrefix() { - return "namespace/document-type/"; - } - - private Response performV1RestCall(String pathPrefix, String pathSuffix, Function<Request, HttpRequestBase> methodOp) { - try { - Request request = new Request(String.format("http://localhost:%s/document/v1/%s%s", - getFirstListenPort(), pathPrefix, pathSuffix)); - HttpRequestBase restOp = methodOp.apply(request); - return doRest(restOp); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - private Response performV1GetRestCall(String pathSuffix) { - return performV1RestCall(defaultPathPrefix(), pathSuffix, (request) -> new HttpGet(request.getUri())); - } - - private void doTestRootPathNotAccepted(Function<Request, HttpRequestBase> methodOpFactory) { - Response response = performV1RestCall("", "", methodOpFactory); - assertHttp400ResponseContains(response, "Root /document/v1/ requests only supported for HTTP GET"); - } - - @Test - public void root_api_path_not_accepted_for_http_put() { - doTestRootPathNotAccepted((request) -> new HttpPut(request.getUri())); - } - - @Test - public void root_api_path_not_accepted_for_http_post() { - doTestRootPathNotAccepted((request) -> new HttpPost(request.getUri())); - } - - @Test - public void root_api_path_not_accepted_for_http_delete() { - doTestRootPathNotAccepted((request) -> new HttpDelete(request.getUri())); - } - - private void assertResultingDocumentSelection(String suffix, String expected) { - Response response = performV1GetRestCall(suffix); - assertHttp200ResponseContains(response, String.format("doc selection: '%s'", expected)); - } - - @Test - public void testUseExpressionOnVisit() throws Exception { - assertResultingDocumentSelection("group/abc?continuation=xyz", "id.group=='abc'"); - } - - private void assertGroupDocumentSelection(String group, String expected) { - assertResultingDocumentSelection("group/" + encoded(group), expected); - } - - @Test - public void group_strings_are_escaped() { - assertGroupDocumentSelection("'", "id.group=='\\''"); - assertGroupDocumentSelection("hello 'world'", "id.group=='hello \\'world\\''"); - assertGroupDocumentSelection("' goodbye moon", "id.group=='\\' goodbye moon'"); - } - - private void assertNumericIdFailsParsing(String id) { - Response response = performV1GetRestCall(String.format("number/%s", encoded(id))); - assertHttp400ResponseContains(response, "Failed to parse numeric part of selection URI"); - } - - @Test - public void invalid_numeric_id_returns_error() { - assertNumericIdFailsParsing("123a"); - assertNumericIdFailsParsing("a123"); - assertNumericIdFailsParsing("0x1234"); - assertNumericIdFailsParsing("\u0000"); - } - - @Test - public void non_text_group_string_character_returns_error() { - Response response = performV1GetRestCall(String.format("group/%s", encoded("\u001f"))); - assertHttp400ResponseContains(response, "Failed to parse group part of selection URI; contains invalid text code point U001F"); - } - - @Test - public void can_specify_numeric_id_without_explicit_selection() { - assertResultingDocumentSelection("number/1234", "id.user==1234"); - } - - @Test - public void can_specify_group_id_without_explicit_selection() { - assertResultingDocumentSelection("group/foo", "id.group=='foo'"); - } - - @Test - public void can_specify_both_numeric_id_and_explicit_selection() { - assertResultingDocumentSelection(String.format("number/1234?selection=%s", encoded("1 != 2")), - "id.user==1234 and (1 != 2)"); - } - - @Test - public void can_specify_both_group_id_and_explicit_selection() { - assertResultingDocumentSelection(String.format("group/bar?selection=%s", encoded("3 != 4")), - "id.group=='bar' and (3 != 4)"); - } - - private void assertDocumentSelectionFailsParsing(String expression) { - Response response = performV1GetRestCall(String.format("number/1234?selection=%s", encoded(expression))); - assertHttp400ResponseContains(response, "Failed to parse expression given in 'selection' parameter. Must be a complete and valid sub-expression."); - } - - // Make sure that typoing the selection parameter doesn't corrupt the entire selection expression - @Test - public void explicit_selection_sub_expression_is_validated_for_completeness() { - assertDocumentSelectionFailsParsing("1 +"); - assertDocumentSelectionFailsParsing(") or true"); - assertDocumentSelectionFailsParsing("((1 + 2)"); - assertDocumentSelectionFailsParsing("true) or (true"); - } - - @Test - public void wanted_document_count_returned_parameter_is_propagated() { - Request request = new Request(String.format("http://localhost:%s/document/v1/namespace/document-type/docid/?wantedDocumentCount=321", getFirstListenPort())); - HttpGet get = new HttpGet(request.getUri()); - assertHttp200ResponseContains(doRest(get), "min docs returned: 321"); - } - - @Test - public void invalid_wanted_document_count_parameter_returns_error_response() { - Request request = new Request(String.format("http://localhost:%s/document/v1/namespace/document-type/docid/?wantedDocumentCount=aardvark", getFirstListenPort())); - HttpGet get = new HttpGet(request.getUri()); - assertHttp400ResponseContains(doRest(get), "Invalid 'wantedDocumentCount' value. Expected positive integer"); - } - - @Test - public void negative_document_count_parameter_returns_error_response() { - Request request = new Request(String.format("http://localhost:%s/document/v1/namespace/document-type/docid/?wantedDocumentCount=-1", getFirstListenPort())); - HttpGet get = new HttpGet(request.getUri()); - assertHttp400ResponseContains(doRest(get), "Invalid 'wantedDocumentCount' value. Expected positive integer"); - } - - @Test - public void visit_fieldset_parameter_is_propagated() { - Request request = new Request(String.format("http://localhost:%s/document/v1/namespace/document-type/docid/?fieldSet=foo,baz", getFirstListenPort())); - HttpGet get = new HttpGet(request.getUri()); - assertHttp200ResponseContains(doRest(get), "field set: 'foo,baz'"); - } - - @Test - public void visit_concurrency_parameter_is_propagated() { - Request request = new Request(String.format("http://localhost:%s/document/v1/namespace/document-type/docid/?concurrency=42", getFirstListenPort())); - HttpGet get = new HttpGet(request.getUri()); - assertHttp200ResponseContains(doRest(get), "concurrency: 42"); - } - - @Test - public void root_api_visit_cluster_parameter_is_propagated() { - Request request = new Request(String.format("http://localhost:%s/document/v1/?cluster=vaffel", getFirstListenPort())); - HttpGet get = new HttpGet(request.getUri()); - assertHttp200ResponseContains(doRest(get), "cluster: 'vaffel'"); - } - - @Test - public void root_api_visit_selection_parameter_is_propagated() { - Request request = new Request(String.format("http://localhost:%s/document/v1/?cluster=foo&selection=yoshi", getFirstListenPort())); - HttpGet get = new HttpGet(request.getUri()); - assertHttp200ResponseContains(doRest(get), "doc selection: 'yoshi'"); - } - - @Test - public void root_api_visit_bucket_space_parameter_is_propagated() { - Request request = new Request(String.format("http://localhost:%s/document/v1/?cluster=foo&bucketSpace=global", getFirstListenPort())); - HttpGet get = new HttpGet(request.getUri()); - assertHttp200ResponseContains(doRest(get), "bucket space: 'global'"); - } - - @Test - public void invalid_visit_concurrency_parameter_returns_error_response() { - Request request = new Request(String.format("http://localhost:%s/document/v1/namespace/document-type/docid/?concurrency=badgers", getFirstListenPort())); - HttpGet get = new HttpGet(request.getUri()); - assertHttp400ResponseContains(doRest(get), "Invalid 'concurrency' value. Expected positive integer"); - } - - private void assertHttpResponseContains(Response response, int expectedStatusCode, String expectedSubstring) { - assertThat(response.code, is(expectedStatusCode)); - assertThat(response.body, containsString(expectedSubstring)); - } - - private void assertHttp200ResponseContains(Response response, String expectedSubstring) { - assertHttpResponseContains(response, 200, expectedSubstring); - } - - private void assertHttp400ResponseContains(Response response, String expectedSubstring) { - assertHttpResponseContains(response, 400, expectedSubstring); - } - - private Response doRest(HttpRequestBase request) { - HttpClient client = HttpClientBuilder.create().build(); - try { - HttpResponse response = client.execute(request); - assertThat(response.getEntity().getContentType().getValue().toString(), startsWith("application/json;")); - HttpEntity entity = response.getEntity(); - return new Response(response.getStatusLine().getStatusCode(), EntityUtils.toString(entity)); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } - - private String getFirstListenPort() { - JettyHttpServer serverProvider = - (JettyHttpServer) Container.get().getServerProviderRegistry().allComponents().get(0); - return Integer.toString(serverProvider.getListenPort()); - } - -} diff --git a/vespaclient-container-plugin/src/test/java/com/yahoo/document/restapi/resource/RestApiWithTestDocumentHandler.java b/vespaclient-container-plugin/src/test/java/com/yahoo/document/restapi/resource/RestApiWithTestDocumentHandler.java deleted file mode 100644 index db782877a6f..00000000000 --- a/vespaclient-container-plugin/src/test/java/com/yahoo/document/restapi/resource/RestApiWithTestDocumentHandler.java +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.document.restapi.resource; - -import com.yahoo.container.logging.AccessLog; -import com.yahoo.document.DataType; -import com.yahoo.document.DocumentType; -import com.yahoo.document.DocumentTypeManager; -import com.yahoo.document.restapi.OperationHandler; - -import java.util.concurrent.Executor; - -/** - * For setting up RestApi with a simple document type manager. - * - * @author dybis - */ -public class RestApiWithTestDocumentHandler extends RestApi{ - - private DocumentTypeManager docTypeManager = new DocumentTypeManager(); - - public RestApiWithTestDocumentHandler( - Executor executor, - AccessLog accessLog, - OperationHandler operationHandler) { - super(executor, accessLog, operationHandler, 20); - - DocumentType documentType = new DocumentType("testdocument"); - - documentType.addField("title", DataType.STRING); - documentType.addField("body", DataType.STRING); - docTypeManager.registerDocumentType(documentType); - - setDocTypeManagerForTests(docTypeManager); - } - -} |