blob: f172a4776f6de16853d1704399d3c38cc50cdf15 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.usergrid.rest.applications.collection;
import com.fasterxml.jackson.databind.JsonNode;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.usergrid.persistence.Schema;
import org.apache.usergrid.persistence.entities.Application;
import org.apache.usergrid.persistence.index.utils.UUIDUtils;
import org.apache.usergrid.rest.test.resource.AbstractRestIT;
import org.apache.usergrid.rest.test.resource.model.*;
import org.apache.usergrid.rest.test.resource.model.Collection;
import org.junit.Ignore;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ws.rs.BadRequestException;
import javax.ws.rs.ClientErrorException;
import java.io.IOException;
import java.util.*;
import static junit.framework.TestCase.assertNotNull;
import static org.junit.Assert.*;
/**
* @author zznate
* @author tnine
* @author rockerston
*
* misc tests for collections
*/
public class CollectionsResourceIT extends AbstractRestIT {
private final String REGION_SETTING = "authoritativeRegion";
private static final Logger log = LoggerFactory.getLogger( CollectionsResourceIT.class );
/***
*
* Test to make sure we get a 400 back when posting to a bad path
*
*/
@Test
public void postToBadPath() throws IOException {
String app = "fakeapp";
String org = this.clientSetup.getOrganizationName();
String entity = "fakeentity";
//try to do a GET on a bad path
try {
this.clientSetup.getRestClient().org(org).app(app).collection("cities").get();
fail("Call to bad path exists, but it should not");
} catch (ClientErrorException e) {
//verify the correct error was returned
JsonNode node = mapper.readTree( e.getResponse().readEntity( String.class ));
assertEquals( "organization_application_not_found", node.get( "error" ).textValue() );
}
//try to do a POST on a bad path
Entity payload = new Entity();
payload.put("name", "Austin");
payload.put("state", "TX");
try {
this.clientSetup.getRestClient().org(org).app(app).collection("cities").post(payload);
fail("Call to bad path exists, but it should not");
} catch (ClientErrorException e) {
//verify the correct error was returned
JsonNode node = mapper.readTree( e.getResponse().readEntity( String.class ));
assertEquals( "organization_application_not_found", node.get( "error" ).textValue() );
}
//try to do a PUT on a bad path
try {
this.clientSetup.getRestClient().org(org).app(app).collection("cities").entity(entity).put(payload);
fail("Call to bad path exists, but it should not");
} catch (ClientErrorException e) {
//verify the correct error was returned
JsonNode node = mapper.readTree( e.getResponse().readEntity( String.class ));
assertEquals( "organization_application_not_found", node.get( "error" ).textValue() );
}
//try to do a delete on a bad path
try {
this.clientSetup.getRestClient().org(org).app(app).collection("cities").entity(entity).delete();
fail("Call to bad path exists, but it should not");
} catch (ClientErrorException e) {
//verify the correct error was returned
JsonNode node = mapper.readTree( e.getResponse().readEntity( String.class ));
assertEquals( "organization_application_not_found", node.get( "error" ).textValue() );
}
}
@Test
public void postToCollectionSchemaUsingOrgAppCreds(){
//Creating schema.
//this could be changed to a hashmap.
ArrayList<String> indexingArray = new ArrayList<>( );
//field "fields" is required.
Entity payload = new Entity();
payload.put( "fields", indexingArray);
Credentials appCredentials = clientSetup.getAppCredentials();
try {
this.pathResource( getOrgAppPath( "testcollections/_settings" ) ).post( false, payload,
new QueryParameters().addParam( "grant_type", "client_credentials" ).addParam( "client_id",
String.valueOf( ( ( Map ) appCredentials.get( "credentials" ) ).get( "client_id" ) ) )
.addParam( "client_secret", String.valueOf(
( ( Map ) appCredentials.get( "credentials" ) ).get( "client_secret" ) ) ) );
}catch(Exception e){
fail("This should return a success.");
}
waitForQueueDrainAndRefreshIndex();
Collection collection = this.app().collection( "testCollections" ).collection( "_settings" ).get();
LinkedHashMap testCollectionSchema = (LinkedHashMap)collection.getResponse().getData();
assertEquals( "app credentials",testCollectionSchema.get( "lastUpdateBy" ) );
assertEquals( 0,testCollectionSchema.get( "lastReindexed" ) );
}
@Test
public void deleteCollectionSchema() throws Exception {
//Creating schema.
//this could be changed to a hashmap.
ArrayList<String> indexingArray = new ArrayList<>( );
//field "fields" is required.
Entity payload = new Entity();
payload.put( "fields", indexingArray);
//Post index to the collection metadata
Entity thing = this.app().collection( "testCollections" ).collection( "_settings" ).post( payload );
waitForQueueDrainAndRefreshIndex();
//The above verifies the test case.
//Create test collection with a test entity that is partially indexed.
Entity testEntity = new Entity();
testEntity.put( "one", "helper" );
testEntity.put( "two","query" );
//Post entity.
Entity postedEntity = this.app().collection( "testCollections" ).post( testEntity );
waitForQueueDrainAndRefreshIndex();
//Do a query to see if you can find the indexed query.
String query = "two ='query'";
QueryParameters queryParameters = new QueryParameters().setQuery(query);
//having a name breaks it. Need to get rid of the stack trace and also
Collection tempEntity = this.app().collection( "testCollections" ).get(queryParameters,true);
assertEquals( 0,tempEntity.getResponse().getEntities().size() );
//Verify if you can query on an entity that was not indexed and that no entities are returned.
query = "one = 'helper'";
queryParameters = new QueryParameters().setQuery(query);
tempEntity = this.app().collection( "testCollections" ).get(queryParameters,true);
assertEquals(0,tempEntity.getResponse().getEntities().size());
query = "uuid = "+postedEntity.getUuid().toString();
queryParameters = new QueryParameters().setQuery(query);
tempEntity = this.app().collection( "testCollections" ).get(queryParameters,true);
assertEquals(1,tempEntity.getResponse().getEntities().size());
//since the collection schema doesn't index anything it shouldn't show up except for the default properties
//to prove that the entity exists
//next part is to delete the schema then reindex it and it should work.
this.app().collection( "testCollections" ).collection( "_settings" ).delete();
waitForQueueDrainAndRefreshIndex();
this.app().collection( "testCollections" ).collection( "_reindex" )
.post(true,clientSetup.getSuperuserToken(),ApiResponse.class,null,null,false);
waitForQueueDrainAndRefreshIndex();
//Do a query to see if you can find the indexed query.
query = "two ='query'";
queryParameters = new QueryParameters().setQuery(query);
//having a name breaks it. Need to get rid of the stack trace and also
tempEntity = this.app().collection( "testCollections" ).get(queryParameters,true);
assertEquals( 1,tempEntity.getResponse().getEntities().size() );
//Verify if you can query on an entity that was not indexed and that no entities are returned.
query = "one = 'helper'";
queryParameters = new QueryParameters().setQuery(query);
tempEntity = this.app().collection( "testCollections" ).get(queryParameters,true);
assertEquals(1,tempEntity.getResponse().getEntities().size());
query = "uuid = "+postedEntity.getUuid().toString();
queryParameters = new QueryParameters().setQuery(query);
tempEntity = this.app().collection( "testCollections" ).get(queryParameters,true);
assertEquals(1,tempEntity.getResponse().getEntities().size());
}
@Test
public void postCollectionSchemaWithWildcardIndexAll() throws Exception {
// setup collection with index all
Entity payload = new Entity();
payload.put( "fields", "all");
app().collection( "testCollection" ).collection( "_settings" ).post( payload );
waitForQueueDrainAndRefreshIndex();
// post entity with two fields
Entity testEntity = new Entity();
testEntity.put( "one", "helper" );
testEntity.put( "two","query" );
app().collection( "testCollection" ).post( testEntity );
waitForQueueDrainAndRefreshIndex();
// verify it can be queried on both fields
String query = "two ='query'";
QueryParameters queryParameters = new QueryParameters().setQuery(query);
Collection tempEntity = app().collection( "testCollection" ).get(queryParameters,true);
Entity reindexedEntity = tempEntity.getResponse().getEntity();
assertEquals( "helper",reindexedEntity.get( "one" ) );
query = "one = 'helper'";
queryParameters = new QueryParameters().setQuery(query);
tempEntity = app().collection( "testCollection" ).get(queryParameters,true);
assertEquals(1,tempEntity.getResponse().getEntities().size());
}
/**
* Create test collection
* Give collection an indexing schema
* Give collection a new entity and ensure it only indexes wht is in the schema
* Reindex and make sure old entity with full text indexing is reindexed with the schema.
*/
@Test
public void postToCollectionSchemaUpdateExistingCollection() throws Exception {
//Create test collection with test entity that is full text indexed.
Entity testEntity = new Entity();
for(int i = 0; i < 10; i++){
testEntity.put( "one","value"+i );
testEntity.put( "two","valuetwo"+i );
this.app().collection( "testCollection" ).post( testEntity );
}
//Creating schema.
//this could be changed to a hashmap.
ArrayList<String> indexingArray = new ArrayList<>( );
indexingArray.add( "one" );
//field "fields" is required.
Entity payload = new Entity();
payload.put( "fields", indexingArray);
//Post index to the collection metadata
Entity thing = this.app().collection( "testCollection" ).collection( "_settings" ).post( payload );
waitForQueueDrainAndRefreshIndex();
//Reindex and verify that the entity only has field one index.
this.app().collection( "testCollection" ).collection( "_reindex" )
.post(true,clientSetup.getSuperuserToken(),ApiResponse.class,null,null,false);
for(int i = 0; i < 10; i++) {
String query = "one ='value"+ i + "'";
QueryParameters queryParameters = new QueryParameters().setQuery( query );
//having a name breaks it. Need to get rid of the stack trace and also
Collection tempEntity = this.app().collection( "testCollection" ).get( queryParameters, true );
Entity reindexedEntity = tempEntity.getResponse().getEntity();
assertEquals( "value"+i, reindexedEntity.get( "one" ) );
//Verify if you can query on an entity that was not indexed and that no entities are returned.
query = "two = 'valuetwo1"+ i + "'";
queryParameters = new QueryParameters().setQuery( query );
tempEntity = this.app().collection( "testCollection" ).get( queryParameters, true );
assertEquals( 0, tempEntity.getResponse().getEntities().size() );
}
}
@Test
public void postToCollectionSchemaAndVerifyFieldsAreUpdated() throws Exception {
//Create test collection with test entity that is full text indexed.
Entity testEntity = new Entity();
for(int i = 0; i < 10; i++){
testEntity.put( "one","value"+i );
testEntity.put( "two","valuetwo"+i );
this.app().collection( "testCollection" ).post( testEntity );
}
//Creating schema.
//this could be changed to a hashmap.
ArrayList<String> indexingArray = new ArrayList<>( );
indexingArray.add( "one" );
//field "fields" is required.
Entity payload = new Entity();
payload.put( "fields", indexingArray);
//Post index to the collection metadata
Entity thing = this.app().collection( "testCollection" ).collection( "_settings" ).post( payload );
waitForQueueDrainAndRefreshIndex();
Collection collection = this.app().collection( "testCollection" ).collection( "_settings" ).get();
LinkedHashMap testCollectionSchema = (LinkedHashMap)collection.getResponse().getData();
assertEquals( ( thing ).get( "lastUpdated" ), testCollectionSchema.get( "lastUpdated" ));
assertEquals( ( thing ).get( "lastUpdateBy" ),testCollectionSchema.get( "lastUpdateBy" ) );
assertEquals( 0,testCollectionSchema.get( "lastReindexed" ) );
ArrayList<String> schema = ( ArrayList<String> ) testCollectionSchema.get( "fields" );
assertEquals( "one",schema.get( 0 ) );
//Reindex and verify that the entity only has field one index.
this.app().collection( "testCollection" ).collection( "_reindex" )
.post(true,clientSetup.getSuperuserToken(),ApiResponse.class,null,null,false);
indexingArray.add( "one" );
indexingArray.add( "two" );
//field "fields" is required.
payload = new Entity();
payload.put( "fields", indexingArray);
//Post index to the collection metadata
this.app().collection( "testCollection" ).collection( "_settings" ).post( payload );
collection = this.app().collection( "testCollection" ).collection( "_settings" ).get();
testCollectionSchema = (LinkedHashMap)collection.getResponse().getData();
assertNotEquals( ( thing ).get( "lastUpdated" ), testCollectionSchema.get( "lastUpdated" ));
assertEquals( ( thing ).get( "lastUpdateBy" ),testCollectionSchema.get( "lastUpdateBy" ) );
assertNotEquals( 0,testCollectionSchema.get( "lastReindexed" ) );
schema = ( ArrayList<String> ) testCollectionSchema.get( "fields" );
assertEquals( "one",schema.get( 0 ) );
for(int i = 0; i < 10; i++) {
String query = "one ='value"+ i + "'";
QueryParameters queryParameters = new QueryParameters().setQuery( query );
//having a name breaks it. Need to get rid of the stack trace and also
Collection tempEntity = this.app().collection( "testCollection" ).get( queryParameters, true );
Entity reindexedEntity = tempEntity.getResponse().getEntity();
assertEquals( "value"+i, reindexedEntity.get( "one" ) );
//Verify if you can query on an entity that was not indexed and that no entities are returned.
query = "two = 'valuetwo1"+ i + "'";
queryParameters = new QueryParameters().setQuery( query );
tempEntity = this.app().collection( "testCollection" ).get( queryParameters, true );
assertEquals( 0, tempEntity.getResponse().getEntities().size() );
}
}
/**
* Create test collection
* Give collection an indexing schema
* Give collection a new entity and ensure it only indexes wht is in the schema
* Reindex and make sure old entity with full text indexing is reindexed with the schema.
*
* @throws Exception
*/
@Test
public void postToCollectionSchemaWithSchemaFirst() throws Exception {
//Include the property labeled two to be index.
ArrayList<String> indexingArray = new ArrayList<>( );
indexingArray.add( "two" );
//field "fields" is required.
Entity payload = new Entity();
payload.put( "fields", indexingArray);
//Post index to the collection metadata
this.app().collection( "testCollection" ).collection( "_settings" ).post( payload );
waitForQueueDrainAndRefreshIndex();
//Create test collection with a test entity that is partially indexed.
Entity testEntity = new Entity();
testEntity.put( "one", "helper" );
testEntity.put( "two","query" );
//Post entity.
this.app().collection( "testCollection" ).post( testEntity );
waitForQueueDrainAndRefreshIndex();
//Do a query to see if you can find the indexed query.
String query = "two ='query'";
QueryParameters queryParameters = new QueryParameters().setQuery(query);
//having a name breaks it. Need to get rid of the stack trace and also
Collection tempEntity = this.app().collection( "testCollection" ).get(queryParameters,true);
Entity reindexedEntity = tempEntity.getResponse().getEntity();
assertEquals( "helper",reindexedEntity.get( "one" ) );
//Verify if you can query on an entity that was not indexed and that no entities are returned.
query = "one = 'helper'";
queryParameters = new QueryParameters().setQuery(query);
tempEntity = this.app().collection( "testCollection" ).get(queryParameters,true);
assertEquals(0,tempEntity.getResponse().getEntities().size());
}
@Test
public void postToCollectionArraySchemaWithSchemaFirst() throws Exception {
//Include the property labeled two to be index.
ArrayList<String> indexingArray = new ArrayList<>( );
indexingArray.add( "two" );
indexingArray.add( "one.key" );
//field "fields" is required.
Entity payload = new Entity();
payload.put( "fields", indexingArray);
//Post index to the collection metadata
this.app().collection( "testCollection" ).collection( "_settings" ).post( payload );
waitForQueueDrainAndRefreshIndex();
Map<String,Object> arrayFieldsForTesting = new HashMap<>();
arrayFieldsForTesting.put( "key","value" );
arrayFieldsForTesting.put( "anotherKey","value2");
//Create test collection with a test entity that is partially indexed.
Entity testEntity = new Entity();
testEntity.put( "one", arrayFieldsForTesting );
testEntity.put( "two","query" );
//Post entity.
this.app().collection( "testCollection" ).post( testEntity );
waitForQueueDrainAndRefreshIndex();
//Do a query to see if you can find the indexed query.
String query = "one.key = 'value'";
QueryParameters queryParameters = new QueryParameters().setQuery(query);
//having a name breaks it. Need to get rid of the stack trace and also
Collection tempEntity = this.app().collection( "testCollection" ).get(queryParameters,true);
Entity reindexedEntity = tempEntity.getResponse().getEntity();
assertEquals( "value2",((Map)reindexedEntity.get( "one" )).get( "anotherKey" ) );
//Verify if you can query on an entity that was not indexed and that no entities are returned.
query = "one.anotherKey = 'value2'";
queryParameters = new QueryParameters().setQuery(query);
tempEntity = this.app().collection( "testCollection" ).get(queryParameters,true);
assertEquals(0,tempEntity.getResponse().getEntities().size());
}
//test to reflect if one would index whatever is prefixed with that. Will
//need to do extensive testing to ensure that it will work with different instances.
@Test
public void postToCollectionSchemaArrayWithTopLevelIndexing() throws Exception {
//Include the property labeled two to be index.
ArrayList<String> indexingArray = new ArrayList<>( );
indexingArray.add( "two" );
//this should work such that one.key and one.anotherKey should work.
indexingArray.add( "one" );
//field "fields" is required.
Entity payload = new Entity();
payload.put( "fields", indexingArray);
//Post index to the collection metadata
this.app().collection( "testCollection" ).collection( "_settings" ).post( payload );
waitForQueueDrainAndRefreshIndex();
Map<String,Object> arrayFieldsForTesting = new HashMap<>();
arrayFieldsForTesting.put( "key","value" );
arrayFieldsForTesting.put( "anotherKey","value2");
//Create test collection with a test entity that is partially indexed.
Entity testEntity = new Entity();
testEntity.put( "one", arrayFieldsForTesting );
testEntity.put( "two","query" );
//Post entity.
this.app().collection( "testCollection" ).post( testEntity );
waitForQueueDrainAndRefreshIndex();
//Do a query to see if you can find the indexed query.
String query = "one.key = 'value'";
QueryParameters queryParameters = new QueryParameters().setQuery(query);
//having a name breaks it. Need to get rid of the stack trace and also
Collection tempEntity = this.app().collection( "testCollection" ).get(queryParameters,true);
Entity reindexedEntity = tempEntity.getResponse().getEntity();
assertEquals( "value2",((Map)reindexedEntity.get( "one" )).get( "anotherKey" ) );
}
@Test
public void postToCollectionSchemaArrayWithSelectiveTopLevelIndexing() throws Exception {
//Include the property labeled two to be index.
ArrayList<String> indexingArray = new ArrayList<>( );
indexingArray.add( "two" );
//this should work such that one.key and one.anotherKey should work.
indexingArray.add( "one.key" );
//field "fields" is required.
Entity payload = new Entity();
payload.put( "fields", indexingArray);
//Post index to the collection metadata
this.app().collection( "testCollection" ).collection( "_settings" ).post( payload );
waitForQueueDrainAndRefreshIndex();
Map<String,Object> arrayFieldsForTestingSelectiveIndexing = new HashMap<>();
arrayFieldsForTestingSelectiveIndexing.put( "wowMoreKeys","value" );
arrayFieldsForTestingSelectiveIndexing.put( "thisShouldBeQueryableToo","value2");
Map<String,Object> arrayFieldsForTesting = new HashMap<>();
arrayFieldsForTesting.put( "key",arrayFieldsForTestingSelectiveIndexing );
arrayFieldsForTesting.put( "anotherKey","value2");
//Create test collection with a test entity that is partially indexed.
Entity testEntity = new Entity();
testEntity.put( "one", arrayFieldsForTesting );
testEntity.put( "two","query" );
//Post entity.
this.app().collection( "testCollection" ).post( testEntity );
waitForQueueDrainAndRefreshIndex();
//Do a query to see if you can find the indexed query.
String query = "one.key.wowMoreKeys = 'value'";
QueryParameters queryParameters = new QueryParameters().setQuery(query);
//having a name breaks it. Need to get rid of the stack trace and also
Collection tempEntity = this.app().collection( "testCollection" ).get(queryParameters,true);
Entity reindexedEntity = tempEntity.getResponse().getEntity();
assertEquals( "value2",((Map)reindexedEntity.get( "one" )).get( "anotherKey" ) );
//Verify if you can query on an entity that was not indexed and that no entities are returned.
query = "one.anotherKey = 'value2'";
queryParameters = new QueryParameters().setQuery(query);
tempEntity = this.app().collection( "testCollection" ).get(queryParameters,true);
assertEquals(0,tempEntity.getResponse().getEntities().size());
}
@Test
public void postToCollectionSchemaArrayWithSelectiveTopLevelIndexingAddingDefaultPropertyNames() throws Exception {
//Include the property labeled two to be index.
ArrayList<String> indexingArray = new ArrayList<>( );
indexingArray.add( "two" );
//this should work such that one.key and one.anotherKey should work.
indexingArray.add( "one.key" );
indexingArray.add( "name" );
//field "fields" is required.
Entity payload = new Entity();
payload.put( "fields", indexingArray);
//Post index to the collection metadata
this.app().collection( "testCollection" ).collection( "_settings" ).post( payload );
waitForQueueDrainAndRefreshIndex();
Map<String,Object> arrayFieldsForTestingSelectiveIndexing = new HashMap<>();
arrayFieldsForTestingSelectiveIndexing.put( "wowMoreKeys","value" );
arrayFieldsForTestingSelectiveIndexing.put( "thisShouldBeQueryableToo","value2");
Map<String,Object> arrayFieldsForTesting = new HashMap<>();
arrayFieldsForTesting.put( "key",arrayFieldsForTestingSelectiveIndexing );
arrayFieldsForTesting.put( "anotherKey","value2");
//Create test collection with a test entity that is partially indexed.
Entity testEntity = new Entity();
testEntity.put( "one", arrayFieldsForTesting );
testEntity.put( "two","query" );
testEntity.put( "name","howdy");
//Post entity.
this.app().collection( "testCollection" ).post( testEntity );
waitForQueueDrainAndRefreshIndex();
//Do a query to see if you can find the indexed query.
String query = "name = 'howdy'";
QueryParameters queryParameters = new QueryParameters().setQuery(query);
//having a name breaks it. Need to get rid of the stack trace and also
Collection tempEntity = this.app().collection( "testCollection" ).get(queryParameters,true);
Entity reindexedEntity = tempEntity.getResponse().getEntity();
assertEquals( "howdy",(reindexedEntity.get( "name" )) );
}
/**
* Verify that doing a put goes through and still applies the existing schema.
* @throws Exception
*/
@Test
public void putToCollectionSchema() throws Exception {
//Include the property labeled two to be index.
ArrayList<String> indexingArray = new ArrayList<>( );
indexingArray.add( "one" );
//field "fields" is required.
Entity payload = new Entity();
payload.put( "fields", indexingArray);
//Post index to the collection metadata
this.app().collection( "testCollection" ).collection( "_settings" ).post( payload );
waitForQueueDrainAndRefreshIndex();
//Create test collection with a test entity that is partially indexed.
Entity testEntity = new Entity();
testEntity.put( "one", "two");
testEntity.put( "test", "anotherTest");
//Post entity.
Entity postedEntity = this.app().collection( "testCollection" ).post( testEntity );
waitForQueueDrainAndRefreshIndex();
testEntity.put( "one","three" );
this.app().collection( "testCollection" ).entity( postedEntity.getUuid() ).put( testEntity );
waitForQueueDrainAndRefreshIndex();
//Do a query to see if you can find the indexed query.
String query = "one = 'three'";
QueryParameters queryParameters = new QueryParameters().setQuery(query);
//having a name breaks it. Need to get rid of the stack trace and also
Collection tempEntity = this.app().collection( "testCollection" ).get(queryParameters,true);
Entity reindexedEntity = tempEntity.getResponse().getEntity();
assertEquals( "three",(reindexedEntity.get( "one" )) );
//check that the old value no longer exists in elasticsearch
query = "one = 'two'";
queryParameters = new QueryParameters().setQuery(query);
tempEntity = this.app().collection( "testCollection" ).get(queryParameters,true);
assertEquals(0,tempEntity.getResponse().getEntities().size());
}
/**
* Test posts with a user level token on a path with permissions
*/
//TODO: App level permissions aren't functioning.
@Test
public void permissionWithMeInString() throws Exception {
// create user
String username = "sumeet.agarwal@usergrid.com";
String email = "sumeet.agarwal@usergrid.com";
String password = "secret";
String name = "Sumeet Agarwal";
Entity payload = new Entity();
payload.put("username", username);
payload.put("email", email);
payload.put("password", password);
payload.put("name", name);
Entity user = this.app().collection("users").post(payload);
assertEquals(user.get("username"), username);
assertEquals(user.get("email"), email);
this.waitForQueueDrainAndRefreshIndex();
String collectionName = "nestprofiles";
//create a permission with the path "me" in it
payload = new Entity();
payload.put( "permission", "get,post,put,delete:/"+collectionName+"/**" );
//POST to /users/sumeet.agarwal@usergrid.com/permissions
Entity permission = this.app().collection("users").entity(user).collection("permissions").post(payload);
assertEquals(permission.get("data"), "get,post,put,delete:/"+collectionName+"/**");
//delete the default role, which would allow all authenticated requests
this.app().collection("role").uniqueID("Default").delete();
//log our new user in
//TODO:App Level token is broken it seems. Test won't work with it.
Token appToken = this.getAppUserToken(username, password);
management().token().setToken( appToken );
//now post data
payload = new Entity();
String profileName = "profile-sumeet";
payload.put( "name", profileName );
payload.put( "firstname", "sumeet" );
payload.put( "lastname", "agarwal" );
payload.put( "mobile", "122" );
Entity nestProfile = this.app().collection(collectionName).post(payload);
assertEquals(nestProfile.get("name"), profileName);
this.waitForQueueDrainAndRefreshIndex();
Entity nestprofileReturned = this.app().collection(collectionName).entity(nestProfile).get();
assertEquals(nestprofileReturned.get("name"), profileName);
}
@Test
public void stringWithSpaces() throws IOException {
// create entity with a property with spaces
String collection = "calendarlists";
String summaryOverview = "My Summary";
String calType = "personal";
Entity payload = new Entity();
payload.put("summaryOverview", summaryOverview);
payload.put("caltype", calType);
Entity calendarlistOne = this.app().collection(collection).post(payload );
assertEquals( calendarlistOne.get( "summaryOverview" ), summaryOverview );
assertEquals(calendarlistOne.get("caltype"), calType);
this.waitForQueueDrainAndRefreshIndex();
//post a second entity
payload = new Entity();
String summaryOverviewTwo = "Your Summary";
String calTypeTwo = "personal";
payload.put("summaryOverview", summaryOverviewTwo);
payload.put("caltype", calTypeTwo);
Entity calendarlistTwo = this.app().collection(collection).post(payload);
assertEquals( calendarlistTwo.get( "summaryOverview" ), summaryOverviewTwo );
assertEquals(calendarlistTwo.get("caltype"), calTypeTwo);
//query for the first entity
String query = "summaryOverview = 'My Summary'";
QueryParameters queryParameters = new QueryParameters().setQuery(query);
Collection calendarListCollection = this.app().collection(collection).get(queryParameters);
assertEquals(calendarListCollection.hasNext(), true);
}
@Test
public void testDefaultCollectionReturning() throws IOException {
ApiResponse usersDefaultCollection = this.app().get();
LinkedHashMap collectionHashMap = ( LinkedHashMap ) usersDefaultCollection.getEntity().get( "metadata" );
//make sure you have all the other default collections once you have users in place.
Set<String> system_collections = Schema.getDefaultSchema().getCollectionNames( Application.ENTITY_TYPE );
for(String collectionName : system_collections){
assertNotSame( null,((LinkedHashMap)(collectionHashMap.get( "collections" ))).get( collectionName ));
}
}
@Ignore("Ignored because we no longer retain custom collections after deleting the last entity in a collection"
+ "This test can be used to verify that works when we implement it")
@Test
public void testNewlyCreatedCollectionReturnsWhenEmpty(){
String collectionName = "testDefaultCollectionReturnings";
Map<String,Object> payload = new HashMap( );
payload.put( "hello","test" );
ApiResponse testEntity = this.app().collection( collectionName ).post( payload );
//Verify that the below collection actually does exist.
ApiResponse usersDefaultCollection = this.app().get();
LinkedHashMap collectionHashMap = ( LinkedHashMap ) usersDefaultCollection.getEntity().get( "metadata" );
assertNotSame( null,
((LinkedHashMap)(collectionHashMap.get( "collections" ))).get( collectionName.toLowerCase() ));
this.waitForQueueDrainAndRefreshIndex();
this.app().collection( collectionName ).entity( testEntity.getEntity().getUuid() ).delete();
this.waitForQueueDrainAndRefreshIndex();
//Verify that the collection still exists despite deleting its only entity.)
usersDefaultCollection = this.app().get();
collectionHashMap = ( LinkedHashMap ) usersDefaultCollection.getEntity().get( "metadata" );
assertNotSame( null,
((LinkedHashMap)(collectionHashMap.get( "collections" ))).get( collectionName.toLowerCase() ));
Collection createdCollectionResponse = this.app().collection( collectionName ).get();
assertEquals( 0,createdCollectionResponse.getNumOfEntities() );
}
/**
* Test to verify "name property returns twice in AppServices response" is fixed.
*/
@Test
public void testNoDuplicateFields() throws Exception {
// create user
String name = "fred";
Entity payload = new Entity();
payload.put("name", name);
Entity user = this.app().collection("app_users").post(payload);
assertEquals(user.get("name"), name);
this.waitForQueueDrainAndRefreshIndex();
Entity user2 = this.app().collection("app_users").entity(user).get();
/*
// check REST API response for duplicate name property
// have to look at raw response data, Jackson will remove dups
String s = resource().path( "/test-organization/test-app/app_users/fred" )
.queryParam( "access_token", access_token ).accept( MediaType.APPLICATION_JSON )
.type( MediaType.APPLICATION_JSON_TYPE ).get( String.class );
int firstFred = s.indexOf( "fred" );
int secondFred = s.indexOf( "fred", firstFred + 4 );
Assert.assertEquals( "Should not be more than one name property", -1, secondFred );
*/
}
/**
* Test that when schema is "none" entity gets saved but does not get indexed
*/
@Test
public void postCollectionSchemaWithWildcardIndexNone() throws Exception {
Entity payload = new Entity();
payload.put( "fields", "none");
String randomizer = RandomStringUtils.randomAlphanumeric(10);
String collectionName = "col_" + randomizer;
app().collection( collectionName ).collection( "_settings" ).post( payload );
waitForQueueDrainAndRefreshIndex();
// was the no-index wildcard saved and others ignored?
Collection collection = app().collection( collectionName ).collection( "_settings" ).get();
LinkedHashMap testCollectionSchema = (LinkedHashMap)collection.getResponse().getData();
String schema = (String)testCollectionSchema.get( "fields" );
assertEquals( "none", schema );
// post an entity with a name and a color
String entityName = "name_" + randomizer;
Entity postedEntity = this.app().collection( collectionName )
.post( new Entity().withProp("name", entityName).withProp( "color", "magenta" ) );
// should be able to get entity by ID
Entity getByIdEntity = app().collection( collectionName ).entity( postedEntity.getUuid() ).get();
assertNotNull( getByIdEntity );
assertEquals( postedEntity.getUuid(), getByIdEntity.getUuid() );
// should be able to get entity by name
Entity getByNameEntity = app().collection( collectionName ).entity( entityName ).get();
assertNotNull( getByNameEntity );
assertEquals( postedEntity.getUuid(), getByNameEntity.getUuid() );
// should NOT be able to get entity by query
Iterator<Entity> getByQuery = app().collection( collectionName )
.get( new QueryParameters().setQuery( "select * where color='magenta'" ) ).iterator();
assertFalse( getByQuery.hasNext() );
}
/**
* Test that indexed entities can be connected to un-indexed Entities and connections still work.
*/
@Test
public void testIndexedEntityToUnindexedEntityConnections() {
// create entities in an un-indexed collection
Entity payload = new Entity();
payload.put( "fields", "none");
String randomizer = RandomStringUtils.randomAlphanumeric(10);
String unIndexedCollectionName = "col_" + randomizer;
app().collection( unIndexedCollectionName ).collection( "_settings" ).post( payload );
waitForQueueDrainAndRefreshIndex();
String entityName1 = "unindexed1";
Entity unindexed1 = this.app().collection( unIndexedCollectionName )
.post( new Entity().withProp("name", entityName1).withProp( "color", "violet" ) );
String entityName2 = "unindexed2";
Entity unindexed2 = this.app().collection( unIndexedCollectionName )
.post( new Entity().withProp("name", entityName2).withProp( "color", "violet" ) );
// create an indexed entity
String indexedCollection = "col_" + randomizer;
String indexedEntityName = "indexedEntity";
Entity indexedEntity = this.app().collection( indexedCollection )
.post( new Entity().withProp("name", indexedEntityName).withProp( "color", "orange" ) );
// create connections from indexed entity to un-indexed entities
app().collection(indexedCollection).entity(indexedEntity).connection("likes").entity(unindexed1).post();
app().collection(indexedCollection).entity(indexedEntity).connection("likes").entity(unindexed2).post();
Collection connectionsByGraph = app().collection( indexedCollection )
.entity(indexedEntity).connection( "likes" ).get();
assertEquals( 2, connectionsByGraph.getNumOfEntities() );
Collection connectionsByQuery = app().collection( indexedCollection )
.entity(indexedEntity).connection( "likes" )
.get( new QueryParameters().setQuery( "select * where color='violet'" ));
assertEquals( 0, connectionsByQuery.getNumOfEntities() );
}
/**
* Test that index entities can be connected to un-indexed Entities and connections still work.
*/
@Test
public void testUnindexedEntityToIndexedEntityConnections() {
// create two entities in an indexed collection
String randomizer = RandomStringUtils.randomAlphanumeric(10);
String indexedCollection = "col_" + randomizer;
String indexedEntityName = "indexedEntity";
Entity indexedEntity1 = this.app().collection( indexedCollection )
.post( new Entity().withProp("name", indexedEntityName + "_1").withProp( "color", "orange" ) );
Entity indexedEntity2 = this.app().collection( indexedCollection )
.post( new Entity().withProp("name", indexedEntityName + "_2").withProp( "color", "orange" ) );
// create an un-indexed entity
Entity payload = new Entity();
payload.put( "fields", "none");
String unIndexedCollectionName = "col_" + randomizer;
app().collection( unIndexedCollectionName ).collection( "_settings" ).post( payload );
waitForQueueDrainAndRefreshIndex();
String entityName1 = "unindexed1";
Entity unindexed1 = this.app().collection( unIndexedCollectionName )
.post( new Entity().withProp("name", entityName1).withProp( "color", "violet" ) );
// create connections from un-indexed entity to indexed entities
app().collection(unIndexedCollectionName).entity(unindexed1).connection("likes").entity(indexedEntity1).post();
app().collection(unIndexedCollectionName).entity(unindexed1).connection("likes").entity(indexedEntity2).post();
// should be able to get connections via graph from un-indexed to index
Collection connectionsByGraph = app().collection( indexedCollection )
.entity(unindexed1).connection( "likes" ).get();
assertEquals( 2, connectionsByGraph.getNumOfEntities() );
// should not be able to get connections via query from unindexed to indexed
Collection connectionsByQuery = app().collection( indexedCollection )
.entity(unindexed1).connection( "likes" )
.get( new QueryParameters().setQuery( "select * where color='orange'" ));
assertEquals( 0, connectionsByQuery.getNumOfEntities() );
}
@Test
public void testCollectionAuthoritativeRegion() {
// create collection with settings for index all
String randomizer = RandomStringUtils.randomAlphanumeric(10);
String collectionName = "col_" + randomizer;
app().collection( collectionName ).collection( "_settings" )
.post( new Entity().chainPut( "fields", "all" ) );
waitForQueueDrainAndRefreshIndex();
// get collection settings, should see no region
Collection collection = app().collection( collectionName ).collection( "_settings" ).get();
Map<String, Object> settings = (Map<String, Object>)collection.getResponse().getData();
assertNull( settings.get( REGION_SETTING ));
// set collection region with bad region, expect error
try {
app().collection( collectionName ).collection( "_settings" )
.post( new Entity().chainPut(REGION_SETTING, "us-moon" ) );
fail( "post should have failed");
} catch ( BadRequestException expected ) {}
// set collection region with good region
app().collection( collectionName ).collection( "_settings" )
.post( new Entity().chainPut( REGION_SETTING, "us-east" ) );
// get collection settings see that we have a region
collection = app().collection( collectionName ).collection( "_settings" ).get();
settings = (Map<String, Object>)collection.getResponse().getData();
assertNotNull( settings.get( REGION_SETTING ));
assertEquals( "us-east", settings.get( REGION_SETTING ));
// unset the collection region
app().collection( collectionName ).collection( "_settings" )
.post( new Entity().chainPut( REGION_SETTING, "" ) );
waitForQueueDrainAndRefreshIndex();
// get collection settings, should see no region
collection = app().collection( collectionName ).collection( "_settings" ).get();
settings = (Map<String, Object>)collection.getResponse().getData();
assertNull( settings.get( REGION_SETTING ));
}
@Test
public void testBeingAbleToRetreiveMigratedValues() throws Exception {
Entity notifier = new Entity().chainPut("name", "mynotifier").chainPut("provider", "noop");
ApiResponse notifierNode = this.pathResource(getOrgAppPath("notifier")).post(ApiResponse.class,notifier);
// create user
Map payloads = new HashMap<>( );
payloads.put( "mynotifier","hello world" );
Map statistics = new HashMap<>( );
statistics.put( "sent",1 );
statistics.put( "errors",2 );
Entity payload = new Entity();
payload.put("debug", false);
payload.put( "expectedCount",0 );
payload.put( "finished",1438279671229L);
payload.put( "payloads",payloads);
payload.put( "priority","normal");
payload.put( "state","FINISHED");
payload.put( "statistics",statistics);
this.app().collection("notifications/"+ UUIDUtils.newTimeUUID()).post(payload );
this.waitForQueueDrainAndRefreshIndex();
Collection user2 = this.app().collection("notifications").get();
assertEquals(1,user2.getNumOfEntities());
this.app().collection("notifications/"+ UUIDUtils.newTimeUUID()).put(null,payload );
this.waitForQueueDrainAndRefreshIndex();
user2 = this.app().collection("notifications").get();
assertEquals(2,user2.getNumOfEntities());
}
}