Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
test.java.com.cloudant.tests.ViewsTest Maven / Gradle / Ivy
/*
* Copyright (C) 2011 lightcouch.org
* Copyright (c) 2015 IBM Corp. All rights reserved.
*
* Licensed 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 com.cloudant.tests;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import com.cloudant.client.api.Database;
import com.cloudant.client.api.views.Key;
import com.cloudant.client.api.views.ViewMultipleRequest;
import com.cloudant.client.api.views.ViewRequest;
import com.cloudant.client.api.views.ViewRequestBuilder;
import com.cloudant.client.api.views.ViewResponse;
import com.cloudant.http.HttpConnectionInterceptorContext;
import com.cloudant.test.main.RequiresCloudant;
import com.cloudant.test.main.RequiresDB;
import com.cloudant.tests.util.CloudantClientResource;
import com.cloudant.tests.util.ContextCollectingInterceptor;
import com.cloudant.tests.util.DatabaseResource;
import com.cloudant.tests.util.Utils;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.rules.RuleChain;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@Category(RequiresDB.class)
public class ViewsTest {
@ClassRule
public static CloudantClientResource clientResource = new CloudantClientResource();
@Rule
public DatabaseResource dbResource = new DatabaseResource(clientResource);
private static ContextCollectingInterceptor cci = new ContextCollectingInterceptor();
public static CloudantClientResource interceptedClient = new CloudantClientResource
(CloudantClientHelper.getClientBuilder().interceptors(cci));
public static DatabaseResource interceptedDB = new DatabaseResource(interceptedClient);
@ClassRule
public static RuleChain intercepted = RuleChain.outerRule(interceptedClient).around
(interceptedDB);
private Database db;
@Before
public void setUp() throws Exception {
db = dbResource.get();
Utils.putDesignDocs(db);
}
@Test
public void queryView() throws Exception {
init();
List foos = db.getViewRequestBuilder("example", "foo").newRequest(Key.Type.STRING,
Object.class).includeDocs(true).build().getResponse().getDocsAs(Foo.class);
assertThat(foos.size(), not(0));
}
@Test
public void byKey() throws Exception {
init();
List foos = db.getViewRequestBuilder("example", "foo").newRequest(Key.Type.STRING,
Object.class).includeDocs(true).keys("key-1").build().getResponse().getDocsAs(Foo
.class);
assertThat(foos.size(), is(1));
}
@Test
public void byKeys() throws Exception {
init();
List foos = db.getViewRequestBuilder("example", "foo").newRequest(Key.Type.STRING,
Object.class).includeDocs(true).keys("key-1", "key-2").build().getResponse()
.getDocsAs(Foo.class);
assertThat(foos.size(), is(2));
}
@Test
public void byStartAndEndKey() throws Exception {
init();
List foos = db.getViewRequestBuilder("example", "foo").newRequest(Key.Type.STRING,
Object.class).includeDocs(true).startKey("key-1").endKey("key-2").build()
.getResponse().getDocsAs(Foo.class);
assertThat(foos.size(), is(2));
}
/**
* Assert that passing a boolean key with value 'false'
* in query will produce a result list of
* all false docs.
*/
@Test
public void queryWithStartAndEndBooleanKey() throws Exception {
init();
List result = db.getViewRequestBuilder("example", "boolean").newRequest(Key.Type
.BOOLEAN, Object.class).startKey(false).endKey(false).build()
.getResponse().getValues();
assertThat(result.size(), is(1));
}
/**
* Assert that passing a boolean key with value 'true' in
* queryView will produce a result list of a true doc.
*/
@Test
public void queryPageWithStartAndEndBooleanKey() throws Exception {
init();
ViewResponse result = db.getViewRequestBuilder("example", "boolean")
.newPaginatedRequest(Key.Type.BOOLEAN, Object.class).startKey(true).endKey(true)
.rowsPerPage(2).build()
.getResponse();
List resultList = result.getValues();
assertThat(resultList.size(), is(2));
}
/**
* Assert that passing a string key with double quotes
* or spaces in query and queryView will produce
* a result list without exception.
*/
@Test
public void queryWithStartAndEndStringIntKeyArray() throws Exception {
init();
List result = db.getViewRequestBuilder("example", "spaces_created").newRequest
(Key.Type.COMPLEX, Object.class)
.startKey(Key.complex(" spaces ").add(1))
.endKey(Key.complex(" spaces 1").add(2000))
.build().getResponse().getValues();
assertThat(result.size(), is(2));
}
/**
* Assert that passing a string key with spaces
* in queryPage will produce a result list
* without exception.
*/
@Test
public void queryPageWithStartAndEndStringIntKeyArray() throws Exception {
init();
List result = db.getViewRequestBuilder("example", "spaces_created")
.newPaginatedRequest(Key.Type.COMPLEX, Object.class)
.startKey(Key.complex(" spaces ").add(1))
.endKey(Key.complex(" spaces 0").add(2000))
.rowsPerPage(30).build().getResponse().getValues();
assertThat(result.size(), is(1));
}
/**
* Assert that passing a string key with quotes
* in query will produce a result list
* without exception.
*/
@Test
public void queryWithStartAndEndStringWithQuotesAndIntKeyArray() throws Exception {
init();
List result = db.getViewRequestBuilder("example", "quotes_created").newRequest
(Key.Type.COMPLEX, Object.class)
.startKey(Key.complex("\"quotes\" ").add(1))
.endKey(Key.complex("\"quotes\" 0").add(2000))
.build().getResponse().getValues();
assertThat(result.size(), is(1));
}
/**
* Assert that passing a string key with quotes
* in query will produce a result list
* without exception.
*/
@Test
public void queryPageWithStartAndEndStringWithQuotesAndIntKeyArray() throws Exception {
init();
List result = db.getViewRequestBuilder("example", "quotes_created")
.newPaginatedRequest(Key.Type.COMPLEX, Object.class)
.startKey(Key.complex("\"quotes\" ").add(1))
.endKey(Key.complex("\"quotes\" 1").add(2000))
.rowsPerPage(30).build().getResponse().getValues();
assertThat(result.size(), is(2));
}
/**
* Assert that passing an array of integers in query
* will produce a result list of all docs.
*/
@Test
public void queryWithStartAndEndIntKeyArray() throws Exception {
init();
List result = db.getViewRequestBuilder("example", "created").newRequest
(Key.Type.COMPLEX, Object.class).startKey(Key.complex(1, 10)).endKey(Key.complex
(2000, 5000)).build().getResponse().getKeys();
assertThat(result.size(), is(3));
}
/**
* Assert that passing an array of integers in queryPage
* will produce a result list of two docs.
*/
@Test
public void queryPageWithStartAndEndIntKeyArray() throws Exception {
init();
List result = db.getViewRequestBuilder("example", "created").newPaginatedRequest
(Key.Type.COMPLEX, Object.class).startKey(Key.complex(1, 10)).endKey(Key.complex
(1001, 2000)).rowsPerPage(30).build().getResponse().getValues();
assertThat(result.size(), is(2));
}
/**
* Assert that passing a key in query with an explicit object array of a
* string and integer value will produce a result list with three docs.
*/
@Test
public void queryWithStartAndEndObjectKeyArray() throws Exception {
init();
List result = db.getViewRequestBuilder("example", "creator_created").newRequest
(Key.Type.COMPLEX, Object.class).startKey(Key.complex("uuid").add(1)).endKey(Key
.complex("uuid").add(1010)).build().getResponse()
.getValues();
assertThat(result.size(), is(3));
}
/**
* Assert that passing a key in queryPage with an explicit object array of
* a string and integer value will produce a result list with three docs.
*/
@Test
public void queryPageWithStartAndEndObjectKeyArray() throws Exception {
init();
List result = db.getViewRequestBuilder("example", "creator_created")
.newPaginatedRequest(Key.Type.COMPLEX, Object.class).startKey(Key.complex("uuid")
.add(1)).endKey(Key.complex("uuid").add(1010)
).rowsPerPage(30).build().getResponse().getKeys();
assertThat(result.size(), is(3));
}
/**
* Assert that passing a key in query with an array of number
* values will produce a result list with two docs.
*/
@Test
public void queryWithStartAndEndNumbersKeyArray() throws Exception {
init();
List result = db.getViewRequestBuilder("example", "created_total")
.newRequest
(Key.Type.COMPLEX, Object.class).startKey(Key.complex(1000, 12.00))
.endKey(Key
.complex(1002, 15.00)).build().getResponse().getKeys();
assertThat(result.size(), is(2));
}
/**
* Assert that passing a key in queryPage with an array of number
* values will produce a result list with one doc.
*/
@Test
public void queryPageWithStartAndEndNumbersKeyArray() throws Exception {
init();
List result = db.getViewRequestBuilder("example", "total_created")
.newPaginatedRequest(Key.Type.COMPLEX, Object.class).startKey(Key.complex(10.00,
1)).endKey(Key.complex(11.00, 2000)).rowsPerPage(30).build().getResponse
().getKeys();
assertThat(result.size(), is(1));
}
/**
* Assert that passing a key in query with an array of a boolean, string,
* and integer value will produce a result list with three docs.
*/
@Test
public void queryWithStartAndEndBooleanStringIntegerKeyArray() throws Exception {
init();
List result = db.getViewRequestBuilder("example", "boolean_creator_created")
.newRequest(Key.Type.COMPLEX, Object.class)
.startKey(Key.complex(false).add("uuid").add(1))
.endKey(Key.complex(true).add("uuid").add(2000))
.build().getResponse().getValues();
assertThat(result.size(), is(3));
}
/**
* Assert that passing a key in queryPage with an array of a boolean, string,
* and integer value will produce a result list with one doc.
*/
@Test
public void queryPageWithStartAndEndBooleanStringIntegerKeyArray() throws Exception {
init();
List result = db.getViewRequestBuilder("example", "boolean_creator_created")
.newPaginatedRequest(Key.Type.COMPLEX, Object.class)
.startKey(Key.complex(false).add("uuid").add(1))
.endKey(Key.complex(false).add("uuid").add(2000))
.rowsPerPage(30).build().getResponse().getValues();
assertThat(result.size(), is(1));
}
/**
* Assert that passing a key in query with an array of a integer, boolean,
* and string value will produce a result list with one doc.
*/
@Test
public void queryWithStartAndEndIntegerBooleanStringKeyArray() throws Exception {
init();
List result = db.getViewRequestBuilder("example", "created_boolean_creator")
.newRequest(Key.Type.COMPLEX, Object.class)
.startKey(Key.complex(1000).add(false).add("uuid"))
.endKey(Key.complex(1000).add(false).add("uuid"))
.build().getResponse().getValues();
assertThat(result.size(), is(1));
}
/**
* Assert that passing a key in queryPage with an array of a integer, boolean,
* and string value will produce a result list with two docs.
*/
@Test
public void queryPageWithStartAndEndIntegerBooleanStringKeyArray() throws Exception {
init();
List result = db.getViewRequestBuilder("example", "created_boolean_creator")
.newPaginatedRequest
(Key.Type.COMPLEX, Object.class)
.startKey(Key.complex(1000).add(false).add("uuid"))
.endKey(Key.complex(1002).add(false).add("uuid"))
.rowsPerPage(30).build().getResponse().getValues();
assertThat(result.size(), is(2));
}
/**
* Assert that passing a complex key with integer, string, and
* boolean objects in query will produce a result with
* JSON object values.
* Assert that the keys and values in the query result's
* JSON objects are the same as the expected objects.
*/
@Test
public void queryWithComplexStartEndKeyAndJsonObjectValue() throws Exception {
init();
List result = db.getViewRequestBuilder("example", "boolean_creator_created")
.newRequest
(Key.Type.COMPLEX, JsonObject.class)
.startKey(Key.complex(true).add("uuid").add(1))
.endKey(Key.complex(true).add("uuid").add(2000))
.build().getResponse().getValues();
assertThat(result.size(), is(2));
Gson gson = new Gson();
ArrayList expectedJsonObject = new ArrayList(),
actualJsonObject = new ArrayList();
for (int i = 0; i < result.size(); i++) {
expectedJsonObject.add(multiValueKeyInit(null, i + 1));
//Build a list from the query's results of the JSON objects from 'contentArray'
JsonObject jsonValueObject = result.get(i);
JsonObject actualJsonContentObject = jsonValueObject.get("contentArray")
.getAsJsonArray().get(0).getAsJsonObject();
actualJsonObject.add(actualJsonContentObject);
}
assertJsonObjectKeysAndValues(expectedJsonObject, actualJsonObject);
}
/**
* Assert that passing a complex key with integer, string, and
* boolean objects in queryView will produce a result with
* JSON object values.
* Assert that the keys and values in the page result's
* JSON objects are the same as the expected objects.
*/
@Test
public void queryPageWithComplexStartEndKeyAndJsonObjectValue() throws Exception {
init();
List result = db.getViewRequestBuilder("example", "boolean_creator_created")
.newPaginatedRequest
(Key.Type.COMPLEX, JsonObject.class).startKey(Key.complex(true)
.add("uuid").add(1))
.endKey(Key.complex(true).add("uuid").add(2000)).rowsPerPage(30)
.build().getResponse()
.getValues();
assertThat(result.size(), is(2));
Gson gson = new Gson();
ArrayList expectedJsonObject = new ArrayList(),
actualJsonObject = new ArrayList();
for (int i = 0; i < result.size(); i++) {
expectedJsonObject.add(multiValueKeyInit(null, i + 1));
//Build a list from the query's results of the JSON objects from 'contentArray'
JsonObject actualJsonContentObject = (gson.toJsonTree(result.get(i)))
.getAsJsonObject().get("contentArray")
.getAsJsonArray().get(0).getAsJsonObject();
actualJsonObject.add(actualJsonContentObject);
}
assertJsonObjectKeysAndValues(expectedJsonObject, actualJsonObject);
}
/**
* Assert that passing a complex key with integer, string, and
* boolean objects in query will produce a result with
* JSON array values.
* Assert that the keys and values in the query result's
* JSON arrays are the same as the expected arrays.
*/
@Test
public void queryWithComplexStartEndKeyAndJsonArrayValue() throws Exception {
init();
List result = db.getViewRequestBuilder("example", "creator_boolean_total")
.newRequest
(Key.Type.COMPLEX, JsonArray.class).startKey(Key.complex("uuid")
.add(true).add(1))
.endKey(Key.complex("uuid").add(true).add(2000)).build()
.getResponse()
.getValues();
assertThat(result.size(), is(2));
Gson gson = new Gson();
ArrayList expectedJsonArray = new ArrayList(),
actualJsonArray = new ArrayList();
for (int i = 0; i < result.size(); i++) {
JsonArray expectedArray = new JsonArray();
expectedArray.add(gson.toJsonTree("key-" + (i + 2)));
expectedArray.add(gson.toJsonTree(10.009999999999999787 + i + 1));
expectedJsonArray.add(expectedArray);
//Build a list from the query's results of the JSON value array
JsonArray actualJsonArrayValue = result.get(i);
actualJsonArray.add(actualJsonArrayValue);
}
assertJsonArrayKeysAndValues(expectedJsonArray, actualJsonArray);
}
/**
* Assert that passing a complex key with integer, string, and
* boolean objects in queryView will produce a result with
* JSON array values.
* Assert that the keys and values in the page result's
* JSON arrays are the same as the expected arrays.
*/
@Test
public void queryPageWithComplexStartEndKeyAndJsonArrayValue() throws Exception {
init();
List result = db.getViewRequestBuilder("example", "creator_boolean_total")
.newPaginatedRequest
(Key.Type.COMPLEX, JsonArray.class).startKey(Key.complex("uuid")
.add(true).add(1))
.endKey(Key.complex("uuid").add(true).add(2000)).rowsPerPage(30)
.build().getResponse()
.getValues();
assertThat(result.size(), is(2));
Gson gson = new Gson();
ArrayList expectedJsonArray = new ArrayList(),
actualJsonArray = new ArrayList();
for (int i = 0; i < result.size(); i++) {
JsonArray expectedArray = new JsonArray();
expectedArray.add(gson.toJsonTree("key-" + (i + 2)));
expectedArray.add(gson.toJsonTree(10.009999999999999787 + i + 1));
expectedJsonArray.add(expectedArray);
//Build a list from the query's results of the JSON value array
JsonArray actualJsonArrayValue = result.get(i);
actualJsonArray.add(actualJsonArrayValue);
}
assertJsonArrayKeysAndValues(expectedJsonArray, actualJsonArray);
}
@Test
public void byComplexKey() throws Exception {
init();
List foos = db.getViewRequestBuilder("example", "by_date").newRequest(Key.Type.COMPLEX,
Object.class).includeDocs(true).keys(Key.complex(2011, 10, 15)).reduce(false)
.build().getResponse().getDocsAs(Foo
.class);
assertThat(foos.size(), is(2));
}
@Test
public void byComplexKeys() throws Exception {
init();
Key.ComplexKey complexKey1 = Key.complex(new Integer[]{2011, 10, 15});
Key.ComplexKey complexKey2 = Key.complex(new Integer[]{2013, 12, 17});
List foos = db.getViewRequestBuilder("example", "by_date").newRequest(Key.Type.COMPLEX,
Object.class).includeDocs(true).keys(complexKey1, complexKey2).reduce(false)
.build().getResponse().getDocsAs(Foo
.class);
assertThat(foos.size(), is(3));
}
@Test
public void viewResultEntries() throws Exception {
init();
Collection> rows = db.getViewRequestBuilder
("example",
"by_date").newRequest(Key.Type.COMPLEX,
String.class).reduce(false).build().getResponse().getRows();
assertThat(rows.size(), is(3));
}
@Test
public void scalarValues() throws Exception {
init();
ViewRequestBuilder builder = db.getViewRequestBuilder("example", "by_tag");
int allTags = builder.newRequest(Key.Type.STRING, int.class).build().getSingleValue();
assertThat(allTags, is(4));
long couchDbTags = builder.newRequest(Key.Type.STRING, long.class).keys("couchdb").build()
.getSingleValue();
assertThat(couchDbTags, is(2L));
String javaTags = builder.newRequest(Key.Type.STRING, String.class).keys("java").build()
.getSingleValue();
assertThat(javaTags, is("1"));
}
@Test
public void viewWithNoResult_emptyList() throws IOException {
init();
assertEquals("The results list should be of length 0", 0, db.getViewRequestBuilder
("example", "by_tag").newRequest(Key.Type.STRING, Object.class).keys
("javax").build().getResponse().getKeys().size());
}
@Test
public void viewWithNoResult_nullSingleResult() throws IOException {
init();
assertNull("The single result should be null", db.getViewRequestBuilder("example",
"by_tag").newRequest(Key.Type.STRING,
Object.class).keys
("javax").build().getSingleValue());
}
@Test
public void groupLevel() throws Exception {
init();
List result = db.getViewRequestBuilder("example", "by_date").newRequest(Key.Type
.COMPLEX, Integer.class).groupLevel(2).build().getResponse().getValues();
assertThat(result.size(), is(2));
}
@Test
public void allDocs() throws Exception {
init();
db.save(new Foo());
List allDocIds = db.getAllDocsRequestBuilder().build().getResponse().getDocIds();
assertThat(allDocIds.size(), not(0));
Map idsAndRevs = db.getAllDocsRequestBuilder().build().getResponse()
.getIdsAndRevs();
assertThat(idsAndRevs.size(), not(0));
for (Map.Entry doc : idsAndRevs.entrySet()) {
assertNotNull("The document _rev value should not be null", doc.getValue());
}
}
@Test
public void allDocsWithKeys() throws Exception {
init();
String id1 = db.save(new Foo()).getId();
String id2 = db.save(new Foo()).getId();
//create 3 and 4, but we don't care about the IDs
db.save(new Foo()).getId();
db.save(new Foo()).getId();
List allDocIds = db.getAllDocsRequestBuilder().keys(id1, id2).build().getResponse()
.getDocIds();
assertThat(allDocIds.size(), is(2));
}
/**
* @param index the index to encode.
* @return a three character string representing the given {@code index}.
*/
public static String docTitle(int index) {
return String.format("%03d", index);
}
private void init() {
Foo foo = null;
foo = new Foo("id-1", "key-1");
foo.setTags(Arrays.asList(new String[]{"couchdb", "views"}));
foo.setComplexDate(new int[]{2011, 10, 15});
multiValueKeyInit(foo, 0);
db.save(foo);
foo = new Foo("id-2", "key-2");
foo.setTags(Arrays.asList(new String[]{"java", "couchdb"}));
foo.setComplexDate(new int[]{2011, 10, 15});
multiValueKeyInit(foo, 1);
db.save(foo);
foo = new Foo("id-3", "key-3");
foo.setComplexDate(new int[]{2013, 12, 17});
multiValueKeyInit(foo, 2);
db.save(foo);
}
public static JsonObject multiValueKeyInit(Foo foo, int i) {
//JSON object for multi value key array tests
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("creator", "uuid");
jsonObject.addProperty("created", 1000 + i);
jsonObject.addProperty("boolean", (i != 0));
jsonObject.addProperty("total", 10.01 + i);
jsonObject.addProperty("quotes", "\"quotes\" " + String.valueOf(i));
jsonObject.addProperty("spaces", " spaces " + String.valueOf(i));
jsonObject.addProperty("letters", (char) ('a' + i) + "bc");
jsonObject.addProperty("one", 1);
JsonArray jsonArray = new JsonArray();
jsonArray.add(jsonObject);
if (foo != null) {
foo.setContentArray(jsonArray);
}
return jsonObject;
}
/**
* Helper method to assert that keys and values in two JSON objects are equal.
*
* @param expectedJson the expected JSON element(s)
* @param actualJson the actual JSON element(s) from test result list
*/
private void assertJsonObjectKeysAndValues(ArrayList expectedJson,
ArrayList actualJson) {
assertEquals(expectedJson.size(),
actualJson.size());
for (int i = 0; i < actualJson.size(); i++) {
JsonObject expectedJsonObject = expectedJson.get(i).getAsJsonObject();
JsonObject actualJsonObject = actualJson.get(i).getAsJsonObject();
Iterator> actualJsonIter =
actualJsonObject.entrySet().iterator();
for (Map.Entry expectedJsonMap :
expectedJsonObject.entrySet()) {
String expectedJsonKey = expectedJsonMap.getKey();
JsonElement expectedJsonValue = expectedJsonMap.getValue();
if (actualJsonIter.hasNext()) {
Map.Entry actualJsonMap = actualJsonIter.next();
assertEquals(expectedJsonKey, actualJsonMap.getKey());
assertEquals(expectedJsonValue, actualJsonMap.getValue());
}
}
}
}
/**
* Helper method to assert that keys and values in two JSON arrays are equal.
*
* @param expectedJson the expected JSON element(s)
* @param actualJson the actual JSON element(s) from test result list
*/
private void assertJsonArrayKeysAndValues(ArrayList expectedJson,
ArrayList actualJson) {
assertEquals(expectedJson.size(), actualJson.size());
for (int i = 0; i < actualJson.size(); i++) {
//Check key and values in the JSON array
JsonArray expectedJsonArray = expectedJson.get(i).getAsJsonArray();
JsonArray actualJsonArray = actualJson.get(i).getAsJsonArray();
assertEquals(expectedJsonArray.size(),
actualJsonArray.size());
Iterator actualJsonIter =
actualJsonArray.iterator();
Iterator expectedJsonIter =
expectedJsonArray.iterator();
while (expectedJsonIter.hasNext()) {
JsonElement expectedJsonElement = expectedJsonIter.next();
JsonElement actualJsonElement = actualJsonIter.next();
assertEquals(expectedJsonElement, actualJsonElement);
}
}
}
/**
* Validate that it is possible to POST multiple requests to a view query and that the
* results of each request are as expected.
*
* @throws IOException
*/
@Test
@Category(RequiresCloudant.class)
public void multiRequest() throws IOException {
init();
ViewMultipleRequest multi = db.getViewRequestBuilder("example", "foo")
.newMultipleRequest(Key.Type.STRING, Object.class)
.keys("key-1").add()
.keys("key-2").add()
.keys("key-3").add()
.build();
int i = 1;
List> responses = multi.getViewResponses();
assertEquals("There should be 3 respones for 3 requests", 3, responses.size());
for (ViewResponse response : responses) {
assertEquals("There should be 1 row in each response", 1, response.getRows().size());
assertEquals("The returned key should be key-" + i, "key-" + i, response.getKeys()
.get(0));
i++;
}
}
/**
* Validate that an IllegalStateException is thrown if an attempt is made to build a multi
* request without calling add() before build().
*
* @throws IOException
*/
@Test(expected = IllegalStateException.class)
public void multiRequestBuildOnlyAfterAdd() throws IOException {
ViewMultipleRequest multi = db.getViewRequestBuilder("example", "foo")
.newMultipleRequest(Key.Type.STRING, Object.class)
.keys("key-1").add()
.keys("key-2").build();
}
/**
* Assert that no additional pages are available on an unpaginated request even if additional
* results are available.
*
* @throws Exception
*/
@Test
public void assertNoPagesOnUnpaginated() throws Exception {
init();
ViewResponse response = db.getViewRequestBuilder("example", "foo")
.newRequest(Key.Type.STRING,
Object.class).limit(2).build().getResponse();
assertEquals("There should be 2 keys returned", 2, response.getKeys().size());
assertFalse("There should be no additional pages", response.hasNextPage());
assertNull("The next page should be null", response.nextPage());
}
/**
* Validate that it is possible to loop through pages using an enhanced for loop. Verify that
* the results are expected on each page.
*
* @throws Exception
*/
@Test
public void enhancedForPagination() throws Exception {
init();
ViewRequest paginatedQuery = db.getViewRequestBuilder("example", "foo")
.newPaginatedRequest(Key.Type.STRING,
Object.class).rowsPerPage(1).build();
int i = 1;
for (ViewResponse page : paginatedQuery.getResponse()) {
assertEquals("There should be one key on each page", 1, page.getKeys().size());
assertEquals("The key should be key-" + i, "key-" + i, page.getKeys().get(0));
i++;
}
}
/**
* Assert that an IllegalArgumentException is thrown when rowsPerPage exceeds MAX_INT-1.
*
* @throws Exception
*/
@Test(expected = IllegalArgumentException.class)
public void rowsPerPageValidationMax() throws Exception {
ViewRequest paginatedQuery = db.getViewRequestBuilder("example", "foo")
.newPaginatedRequest(Key.Type.STRING,
Object.class).rowsPerPage(Integer.MAX_VALUE).build();
}
/**
* Assert that an IllegalArgumentException is thrown when rowsPerPage is zero.
*
* @throws Exception
*/
@Test(expected = IllegalArgumentException.class)
public void rowsPerPageValidationZero() throws Exception {
ViewRequest paginatedQuery = db.getViewRequestBuilder("example", "foo")
.newPaginatedRequest(Key.Type.STRING,
Object.class).rowsPerPage(0).build();
}
/**
* Assert that an IllegalArgumentException is thrown when rowsPerPage is negative.
*
* @throws Exception
*/
@Test(expected = IllegalArgumentException.class)
public void rowsPerPageValidationMin() throws Exception {
ViewRequest paginatedQuery = db.getViewRequestBuilder("example", "foo")
.newPaginatedRequest(Key.Type.STRING,
Object.class).rowsPerPage(-25).build();
}
/**
* Assert that an IllegalArgumentException is thrown when specifying both reduce=true and
* include_docs=true
*
* @throws Exception
*/
@Test(expected = IllegalArgumentException.class)
public void validationIncludeDocsReduceView() throws Exception {
ViewRequest paginatedQuery = db.getViewRequestBuilder("example", "foo")
.newRequest(Key.Type.STRING,
Object.class).includeDocs(true).reduce(true).build();
}
/**
* Test that no validation exception is thrown when reduce is not specified, but include_docs
* is true. This is because whilst reduce=true and include_docs=true are mutually exclusive
* and even though reduce defaults to true, if the view does not actually have a reduce function
* then include_docs is still valid on the server.
*
* @throws Exception
*/
@Test
public void noExceptionWhenReduceTrueByDefault() throws Exception {
ViewRequest paginatedQuery = db.getViewRequestBuilder("example", "foo")
.newRequest(Key.Type.STRING,
Object.class).includeDocs(true).build();
}
/**
* Tests than an IllegalArgumentException is thrown when group_level is set without using a
* complex key.
*
* @throws Exception
*/
@Test(expected = IllegalArgumentException.class)
public void validationGroupLevelWithSimpleKey() throws Exception {
ViewRequest paginatedQuery = db.getViewRequestBuilder("example", "foo")
.newRequest(Key.Type.STRING,
Object.class).groupLevel(1).build();
}
/**
* Tests than an IllegalArgumentException is thrown when group_level is set without using a
* reduce view.
*
* @throws Exception
*/
@Test(expected = IllegalArgumentException.class)
public void validationGroupLevelWithNonReduce() throws Exception {
ViewRequest paginatedQuery = db.getViewRequestBuilder("example", "foo")
.newRequest(Key.Type.STRING,
Object.class).reduce(false).groupLevel(1).build();
}
/**
* Tests than an IllegalArgumentException is thrown when group is set without using a
* reduce view.
*
* @throws Exception
*/
@Test(expected = IllegalArgumentException.class)
public void validationGroupWithNonReduce() throws Exception {
ViewRequest paginatedQuery = db.getViewRequestBuilder("example", "foo")
.newRequest(Key.Type.STRING,
Object.class).reduce(false).group(true).build();
}
/**
* Test written for https://github.com/cloudant/java-cloudant/issues/172 where complex key
* integers were being changed to floats when using pagination tokens. For example ["uuid", 1]
* would become ["uuid", 1.0] when trying to request the second page. 1.0 sorts before 1, so the
* wrong documents would be returned on the second page.
*
* The test creates 10 documents that emit complex keys of e.g. ["uuid", 1000]
*
* We use 5 documents per page and use a start key of ["uuid", 1].
*
* The test gets the first page and then retrieves the second page using a token.
* It captures the request URL and then asserts that the startkey was of the correct integer
* form.
*
* @throws Exception
*/
@Test
public void testComplexKeyContainingIntTokenPagination() throws Exception {
// Use the intercepted client as we want to check the query string in the connection
db = interceptedDB.get();
Utils.putDesignDocs(db);
// Create 10 documents in the database
int nDocs = 10;
for (int i = 0; i < nDocs; i++) {
Foo f = new Foo("" + i);
f.setPosition(i);
multiValueKeyInit(f, i);
db.save(f);
}
// Use the creator_created view (complex keys [String, int])
ViewRequest request = db.getViewRequestBuilder("example",
"creator_created").newPaginatedRequest(Key.Type.COMPLEX, Object.class).startKey(Key
.complex("uuid").add(1)).rowsPerPage(5).build();
// Get the second page response by token
ViewResponse response = request.getResponse();
String token = response.getNextPageToken();
request.getResponse(token);
// We want the last context
HttpConnectionInterceptorContext context = cci.contexts.get(cci.contexts.size() - 1);
String query = context.connection.url.getQuery();
assertTrue("The query startkey should match.", query.contains("startkey=%5B%22uuid%22," +
"1005%5D"));
}
/**
* Tests that reserved characters in a view parameter are encoded.
* https://github.com/cloudant/java-cloudant/issues/202
*
* @throws Exception
*/
@Test
public void testUriReservedCharsInStartKey() throws Exception {
char[] reservedChars = new char[]{
// 3986 general delimeters
':', '/', '?', '#', '[', ']', '@',
// 3986 sub delimeters
'!', '$', '&', '\'', '(', ')', '*', '+', ',', ';', '='};
for (char c : reservedChars) {
testUriReservedCharInStartKey(c);
}
}
private void testUriReservedCharInStartKey(char c) throws Exception {
try {
ViewRequest request = db.getViewRequestBuilder("example",
"foo").newPaginatedRequest(Key.Type.STRING, Object.class)
.startKey("a" + c + "b")
.rowsPerPage(5)
.build();
request.getResponse();
// We don't actually need to do anything with the response, just ensure the request does
// not cause an exception.
} catch (Exception e) {
fail("The character " + c + " caused an exception to be thrown.");
}
}
}