diff options
author | Jon Bratseth <bratseth@yahoo-inc.com> | 2016-06-15 23:09:44 +0200 |
---|---|---|
committer | Jon Bratseth <bratseth@yahoo-inc.com> | 2016-06-15 23:09:44 +0200 |
commit | 72231250ed81e10d66bfe70701e64fa5fe50f712 (patch) | |
tree | 2728bba1131a6f6e5bdf95afec7d7ff9358dac50 /vespaclient-container-plugin/src/test/java/com/yahoo/document/restapi/resource/RestApiTest.java |
Publish
Diffstat (limited to 'vespaclient-container-plugin/src/test/java/com/yahoo/document/restapi/resource/RestApiTest.java')
-rw-r--r-- | vespaclient-container-plugin/src/test/java/com/yahoo/document/restapi/resource/RestApiTest.java | 298 |
1 files changed, 298 insertions, 0 deletions
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 new file mode 100644 index 00000000000..036dc63ad34 --- /dev/null +++ b/vespaclient-container-plugin/src/test/java/com/yahoo/document/restapi/resource/RestApiTest.java @@ -0,0 +1,298 @@ +// Copyright 2016 Yahoo Inc. 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.nio.file.Paths; + +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/application"), Networking.enable); + } + + @After + public void tearDown() throws Exception { + application.close(); + } + + 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); + String x = doRest(httpPost); + assertThat(x, 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); + String x = doRest(httpPost); + assertThat(x, is(post_test_response_cond)); + } + + String post_test_empty_response = "{\"errors\":[\"Could not read document, no document?\"]"; + @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); + String x = doRest(httpPost); + assertThat(x, startsWith(post_test_empty_response)); + } + + 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); + assertThat(doRest(httpPut), 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); + assertThat(doRest(httpPut), 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), 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), is(update_test_create_if_non_existing_response)); + assertThat(getLog(), not(containsString("CREATE IF NON EXISTENT IS TRUE"))); + + } + + // 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 wtih 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); + } + + + 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()); + assertThat(doRest(delete), 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()); + final String rest = doRest(get); + assertThat(rest, containsString(get_response_part1)); + assertThat(rest, 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()); + final String rest = doRest(get); + assertThat(rest, containsString(id_response_part1)); + assertThat(rest, 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()); + final String rest = doRest(get); + assertThat(rest, containsString(get_enc_response_part1)); + assertThat(rest, 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()); + final String rest = doRest(get); + assertThat(rest, containsString(get_enc_response_part1_v2)); + assertThat(rest, containsString(get_enc_response_part2)); + } + + 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()); + final String rest = doRest(get); + assertThat(rest, containsString(visit_response_part1)); + assertThat(rest, containsString(visit_response_part2)); + assertThat(rest, containsString(visit_response_part3)); + } + + String visit_test_bad_uri = "/document/v1/namespace/document-type/group/abc?continuation=abc"; + String visit_test_bad_response = "Visiting does not support setting value for group/value,"; + + + @Test + public void testBadVisit() throws Exception { + final Request request = new Request("http://localhost:" + getFirstListenPort() + visit_test_bad_uri); + HttpGet get = new HttpGet(request.getUri()); + final String rest = doRest(get); + assertThat(rest, containsString(visit_test_bad_response)); + } + + private String doRest(HttpRequestBase request) throws IOException { + HttpClient client = HttpClientBuilder.create().build(); + HttpResponse response = client.execute(request); + HttpEntity entity = response.getEntity(); + return EntityUtils.toString(entity); + } + + private String getFirstListenPort() { + JettyHttpServer serverProvider = + (JettyHttpServer) Container.get().getServerProviderRegistry().allComponents().get(0); + return Integer.toString(serverProvider.getListenPort()); + } + +} |