/*
* 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.persistence;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.UUID;
import org.junit.Ignore;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.usergrid.AbstractCoreIT;
import org.apache.usergrid.corepersistence.util.CpNamingUtils;
import org.apache.usergrid.persistence.Query.Level;
import org.apache.usergrid.persistence.entities.Group;
import org.apache.usergrid.persistence.entities.User;
import org.apache.usergrid.persistence.model.util.UUIDGenerator;
import org.apache.usergrid.utils.UUIDUtils;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
public class EntityManagerIT extends AbstractCoreIT {
private static final Logger logger = LoggerFactory.getLogger( EntityManagerIT.class );
public EntityManagerIT() {
super();
}
@Test
public void testEntityManager() throws Exception {
logger.info( "EntityManagerIT.testEntityManagerTest" );
EntityManager em = app.getEntityManager();
assertNotNull( em );
final UUID applicationId = app.getId();
Map<String, Object> properties = new LinkedHashMap<String, Object>();
properties.put( "username", "edanuff" );
properties.put( "email", "ed@anuff.com" );
Entity user = em.create( "user", properties );
assertNotNull( user );
user = em.get( user );
assertNotNull( user );
assertEquals( "user.username not expected value", "edanuff", user.getProperty( "username" ) );
assertEquals( "user.email not expected value", "ed@anuff.com", user.getProperty( "email" ) );
app.waitForQueueDrainAndRefreshIndex();
EntityRef userRef = em.getAlias( new SimpleEntityRef( "application", applicationId ), "users", "edanuff" );
assertNotNull( userRef );
assertEquals( "userRef.id not expected value", user.getUuid(), userRef.getUuid() );
assertEquals( "userRef.type not expected value", "user", userRef.getType() );
logger.info( "user.username: " + user.getProperty( "username" ) );
logger.info( "user.email: " + user.getProperty( "email" ) );
final Query query = Query.fromQL( "username = 'edanuff'" );
Results results = em.searchCollection( em.getApplicationRef(), "users", query );
assertNotNull( results );
assertEquals( 1, results.size() );
user = results.getEntity();
assertNotNull( user );
assertEquals( "user.username not expected value", "edanuff", user.getProperty( "username" ) );
assertEquals( "user.email not expected value", "ed@anuff.com", user.getProperty( "email" ) );
logger.info( "user.username: " + user.getProperty( "username" ) );
logger.info( "user.email: " + user.getProperty( "email" ) );
final Query emailQuery = Query.fromQL( "email = 'ed@anuff.com'" );
results = em.searchCollection( em.getApplicationRef(), "users", emailQuery );
assertNotNull( results );
assertEquals( 1, results.size() );
user = results.getEntity();
assertNotNull( user );
assertEquals( "user.username not expected value", "edanuff", user.getProperty( "username" ) );
assertEquals( "user.email not expected value", "ed@anuff.com", user.getProperty( "email" ) );
logger.info( "user.username: " + user.getProperty( "username" ) );
logger.info( "user.email: " + user.getProperty( "email" ) );
}
@Test
public void testCreateAndGet() throws Exception {
logger.info( "EntityDaoTest.testCreateAndGet" );
EntityManager em = app.getEntityManager();
int i = 0;
List<Entity> things = new ArrayList<Entity>();
for ( i = 0; i < 10; i++ ) {
Map<String, Object> properties = new LinkedHashMap<String, Object>();
properties.put( "name", "thing" + i );
Entity thing = em.create( "thing", properties );
assertNotNull( "thing should not be null", thing );
assertFalse( "thing id not valid", thing.getUuid().equals( new UUID( 0, 0 ) ) );
assertEquals( "name not expected value", "thing" + i, thing.getProperty( "name" ) );
things.add( thing );
}
assertEquals( "should be ten entities", 10, things.size() );
i = 0;
for ( Entity entity : things ) {
Entity thing = em.get( new SimpleEntityRef( "thing", entity.getUuid() ) );
assertNotNull( "thing should not be null", thing );
assertFalse( "thing id not valid", thing.getUuid().equals( new UUID( 0, 0 ) ) );
assertEquals( "name not expected value", "thing" + i, thing.getProperty( "name" ) );
i++;
}
List<UUID> ids = new ArrayList<UUID>();
for ( Entity entity : things ) {
ids.add( entity.getUuid() );
Entity en = em.get( new SimpleEntityRef( "thing", entity.getUuid() ) );
String type = en.getType();
assertEquals( "type not expected value", "thing", type );
Object property = en.getProperty( "name" );
assertNotNull( "thing name property should not be null", property );
assertTrue( "thing name should start with \"thing\"", property.toString().startsWith( "thing" ) );
Map<String, Object> properties = en.getProperties();
assertEquals( "number of properties wrong", 6, properties.size() );
}
i = 0;
Results results = em.getEntities( ids, "thing" );
for ( Entity thing : results ) {
assertNotNull( "thing should not be null", thing );
assertFalse( "thing id not valid", thing.getUuid().equals( new UUID( 0, 0 ) ) );
assertEquals( "wrong type", "thing", thing.getType() );
assertNotNull( "thing name should not be null", thing.getProperty( "name" ) );
String name = thing.getProperty( "name" ).toString();
assertEquals( "unexpected name", "thing" + i, name );
i++;
}
assertEquals( "entities unfound entity name count incorrect", 10, i );
}
@Test
public void testDictionaries() throws Exception {
logger.info( "EntityDaoTest.testDictionaries" );
EntityManager em = app.getEntityManager();
Map<String, Object> properties = new LinkedHashMap<String, Object>();
properties.put( "name", "thing" );
Entity thing = em.create( "thing", properties );
assertNotNull( thing );
em.addToDictionary( thing, "stuff", "alpha" );
em.addToDictionary( thing, "stuff", "beta" );
em.addToDictionary( thing, "stuff", "gamma" );
Set<Object> set = em.getDictionaryAsSet( thing, "stuff" );
assertNotNull( "list should not be null", set );
assertEquals( "Wrong number of items in list", 3, set.size() );
Iterator<Object> i = set.iterator();
logger.info( "first item is " + i.next() );
logger.info( "second item is " + i.next() );
logger.info( "third item is " + i.next() );
i = set.iterator();
assertEquals( "first item should be alpha", "alpha", i.next() );
assertEquals( "second item should be beta", "beta", i.next() );
assertEquals( "third item should be gamma", "gamma", i.next() );
em.addToDictionary( thing, "test", "foo", "bar" );
String val = ( String ) em.getDictionaryElementValue( thing, "test", "foo" );
assertEquals( "val should be bar", "bar", val );
/*
* Results r = em.searchCollection(em.getApplicationRef(), "things",
* Query.findForProperty("stuff", "beta"));
* assertNotNull("results should not be null", r);
* assertEquals("Wrong number of items in list", 1, r.size());
*/
}
@Test
public void testProperties() throws Exception {
logger.info( "EntityDaoTest.testProperties" );
EntityManager em = app.getEntityManager();
Map<String, Object> properties = new LinkedHashMap<String, Object>();
properties.put( "name", "testprop" );
Entity thing = em.create( "thing", properties );
Entity entity = em.get( new SimpleEntityRef( "thing", thing.getUuid() ) );
assertNotNull( "entity should not be null", entity );
em.setProperty( entity, "alpha", 1L );
em.setProperty( entity, "beta", 2L );
em.setProperty( entity, "gamma", 3L );
Map<String, Object> props = em.getProperties( entity );
assertNotNull( "properties should not be null", props );
assertEquals( "wrong number of properties", 9, props.size() );
assertEquals( "wrong value for property alpha", ( long ) 1, props.get( "alpha" ) );
assertEquals( "wrong value for property beta", ( long ) 2, props.get( "beta" ) );
assertEquals( "wrong value for property gamma", ( long ) 3, props.get( "gamma" ) );
for ( Entry<String, Object> entry : props.entrySet() ) {
logger.info( entry.getKey() + " : " + entry.getValue() );
}
em.deleteProperty( entity, "alpha" );
props = em.getProperties( entity );
assertNotNull( "properties should not be null", props );
assertEquals( "wrong number of properties", 8, props.size() );
}
@Test
public void testCreateAndDelete() throws Exception {
logger.info( "EntityDaoTest.testCreateAndDelete" );
EntityManager em = app.getEntityManager();
String name = "test.thing" + UUIDUtils.newTimeUUID();
Map<String, Object> properties = new LinkedHashMap<String, Object>();
properties.put( "name", name );
properties.put( "foo", "bar" );
logger.info( "Starting entity create" );
Entity thing = em.create( "thing", properties );
logger.info( "Entity created" );
app.waitForQueueDrainAndRefreshIndex();
logger.info( "Starting entity delete" );
em.delete( thing );
logger.info( "Entity deleted" );
app.waitForQueueDrainAndRefreshIndex();
// now search by username, no results should be returned
final Query emailQuery = Query.fromQL( "name = '" + name + "'" );
Results r = em.searchCollection( em.getApplicationRef(), "thing", emailQuery );
assertEquals( 0, r.size() );
}
@Test
public void testCreateAndDeleteUser() throws Exception {
logger.info( "EntityDaoTest.testCreateAndDeleteUser" );
EntityManager em = app.getEntityManager();
String name = "test.thing" + UUIDUtils.newTimeUUID();
Map<String, Object> properties = new LinkedHashMap<String, Object>();
properties.put( "username", name );
properties.put( "foo", "bar" );
logger.info( "Starting entity create" );
Entity user = em.create( "user", properties );
logger.info( "Entity created" );
app.waitForQueueDrainAndRefreshIndex();
logger.info( "Starting entity delete" );
em.delete( user );
logger.info( "Entity deleted" );
app.waitForQueueDrainAndRefreshIndex();
// now search by username, no results should be returned
final Query query = Query.fromQL( "username = '" + name + "'" );
Results r = em.searchCollection( em.getApplicationRef(), "users", query );
assertEquals( 0, r.size() );
// now re-create a new user with the same username
properties = new LinkedHashMap<String, Object>();
properties.put( "username", name );
properties.put( "foo", "bar" );
logger.info( "Starting entity create" );
user = em.create( "user", properties );
logger.info( "Entity created" );
app.waitForQueueDrainAndRefreshIndex();
final Query userNameQuery = Query.fromQL( "username = '" + name + "'" );
r = em.searchCollection( em.getApplicationRef(), "users", userNameQuery );
assertEquals( 1, r.size() );
assertEquals( user.getUuid(), r.getEntity().getUuid() );
}
@SuppressWarnings( "unchecked" )
@Test
public void testJson() throws Exception {
logger.info( "EntityDaoTest.testProperties" );
EntityManager em = app.getEntityManager();
Map<String, Object> properties = new LinkedHashMap<String, Object>();
properties.put( "name", "testprop" );
Entity thing = em.create( "thing", properties );
Entity entity = em.get( new SimpleEntityRef( "thing", thing.getUuid() ) );
assertNotNull( "entity should not be null", entity );
Map<String, Object> json = new LinkedHashMap<String, Object>();
json.put( "a", "alpha" );
json.put( "b", "beta" );
json.put( "c", "gamma" );
em.setProperty( entity, "json", json );
Map<String, Object> props = em.getProperties( entity );
assertNotNull( "properties should not be null", props );
assertEquals( "wrong number of properties", 7, props.size() );
json = ( Map<String, Object> ) props.get( "json" );
assertEquals( "wrong size for property alpha", 3, json.size() );
assertEquals( "wrong value for property beta", "alpha", json.get( "a" ) );
em.deleteProperty( entity, "json" );
}
@Test
@Ignore( "Pending https://issues.apache.org/jira/browse/USERGRID-1753. Concurrency issue.")
// There is a concurrency issue due to counters not being thread safe
public void testEntityCounters() throws Exception {
logger.info( "EntityManagerIT#testEntityCounters" );
EntityManager em = app.getEntityManager();
Group organizationEntity = new Group();
organizationEntity.setPath( "testCounterOrg" );
organizationEntity.setProperty( "name", "testCounterOrg" );
organizationEntity = em.create( organizationEntity );
Entity appInfo =
setup.getEmf().createApplicationV2( "testCounterOrg", "testEntityCounters" + UUIDGenerator.newTimeUUID() );
UUID applicationId = appInfo.getUuid();
Map<String, Object> properties = new LinkedHashMap<String, Object>();
properties.put( "name", "testEntityCounters" );
Entity applicationEntity = em.create( applicationId, CpNamingUtils.APPLICATION_INFO, properties );
em.createConnection( new SimpleEntityRef( "group", organizationEntity.getUuid() ), "owns",
new SimpleEntityRef( CpNamingUtils.APPLICATION_INFO, applicationId ) );
em = setup.getEmf().getEntityManager( applicationId );
properties = new LinkedHashMap<String, Object>();
properties.put( "username", "edanuff" );
properties.put( "email", "ed@anuff.com" );
Entity user = em.create( "user", properties );
em = setup.getEmf().getEntityManager( setup.getEmf().getManagementAppId() );
Map<String, Long> counts = em.getEntityCounters( setup.getEmf().getManagementAppId() );
logger.info( "Entity counters: {}", counts );
assertNotNull( counts );
assertEquals( 4, counts.size() );
Entity entity = em.get( new SimpleEntityRef( Group.ENTITY_TYPE, organizationEntity.getUuid() ) );
assertEquals( "testCounterOrg", entity.getName() );
em = setup.getEmf().getEntityManager( applicationId );
counts = em.getEntityCounters( applicationId );
logger.info( "Entity counters: {}", counts );
assertNotNull( counts );
assertEquals( 3, counts.size() );
}
@Test
public void testCreateAndList() throws Exception {
logger.info( "EntityDaoTest.testCreateAndDelete" );
EntityManager em = app.getEntityManager();
String name = "test.thing" + UUIDUtils.newTimeUUID() + 1;
Map<String, Object> properties = new LinkedHashMap<String, Object>();
properties.put( "name", name );
properties.put( "foo", "bar" );
logger.info( "Starting entity create" );
Entity thing1 = em.create( "thing", properties );
logger.info( "Entity created" );
String name2 = "test.thing" + UUIDUtils.newTimeUUID() + 2;
properties = new LinkedHashMap<String, Object>();
properties.put( "name", name2 );
properties.put( "foo", "bar" );
logger.info( "Starting entity create" );
Entity thing2 = em.create( "thing", properties );
logger.info( "Entity created" );
// now search by username, no results should be returned
EntityRef appRef = em.get( new SimpleEntityRef( "application", app.getId() ) );
app.waitForQueueDrainAndRefreshIndex();
Results r = em.getCollection( appRef, "things", null, 10, Level.ALL_PROPERTIES, false );
assertEquals( 2, r.size() );
assertEquals( thing1.getUuid(), r.getEntities().get( 1 ).getUuid() );
assertEquals( thing2.getUuid(), r.getEntities().get( 0 ).getUuid() );
}
@Test
public void testCorrectType() throws Exception {
EntityManager em = app.getEntityManager();
Map<String, Object> properties = new LinkedHashMap<String, Object>();
properties.put( "name", "testuser" );
properties.put( "username", "testuser" );
properties.put( "email", "test@foo.bar" );
Entity created = em.create( "user", properties );
Entity returned = em.get( new SimpleEntityRef( "user", created.getUuid() ) );
assertNotNull( created );
assertNotNull( returned );
assertTrue( created instanceof User );
assertTrue( returned instanceof User );
assertEquals( created, returned );
}
@Test
public void testImmutableForcedPropChange() throws Exception {
logger.info( "EntityDaoTest.testProperties" );
EntityManager em = app.getEntityManager();
Map<String, Object> properties = new LinkedHashMap<String, Object>();
properties.put( "name", "one" );
Entity saved = em.create( "thing", properties );
Entity thingOne = em.get( new SimpleEntityRef( "thing", saved.getUuid() ) );
assertNotNull( "entity should not be null", thingOne );
assertEquals( "one", thingOne.getProperty( "name" ).toString() );
em.setProperty( thingOne, "name", "two", true );
Entity thingTwo = em.get( new SimpleEntityRef( "thing", saved.getUuid() ) );
assertEquals( "two", thingTwo.getProperty( "name" ) );
}
@Test
public void ownershipScopeCorrect() throws Exception {
EntityManager em = app.getEntityManager();
//first user
Map<String, Object> userProps = new LinkedHashMap<String, Object>();
userProps.put( "name", "testuser" );
userProps.put( "username", "testuser" );
userProps.put( "email", "test@foo.bar" );
Entity createdUser = em.create( "user", userProps );
Entity returnedUser = em.get( new SimpleEntityRef( "user", createdUser.getUuid() ) );
assertNotNull( createdUser );
assertNotNull( returnedUser );
//second user
Map<String, Object> userProps2 = new LinkedHashMap<String, Object>();
userProps2.put( "name", "testuser2" );
userProps2.put( "username", "testuser2" );
userProps2.put( "email", "test2@foo.bar" );
Entity createdUser2 = em.create( "user", userProps2 );
Entity returnedUser2 = em.get( new SimpleEntityRef( "user", createdUser2.getUuid() ) );
assertNotNull( createdUser2 );
assertNotNull( returnedUser2 );
//now create the device, in the scope of the user
Map<String, Object> device = new LinkedHashMap<String, Object>();
device.put( "name", "device1" );
Entity createdDevice = em.createItemInCollection( createdUser, "devices", "device", device );
app.waitForQueueDrainAndRefreshIndex();
Entity returnedDevice = em.get( new SimpleEntityRef( "device", createdDevice.getUuid() ) );
assertNotNull( createdDevice );
assertNotNull( returnedDevice );
assertEquals( "device1", returnedDevice.getName() );
//now load it within the context of the user, it should load.
//first user is an owner
assertTrue( em.isCollectionMember( createdUser, "devices", createdDevice ) );
//Not an owner
assertFalse( em.isCollectionMember( createdUser2, "devices", createdDevice ) );
}
@Test
public void testDeprecatedGet() throws Exception {
logger.info( "EntityManagerIT.testDeprecatedGet" );
EntityManager em = app.getEntityManager();
Map<String, Object> properties = new LinkedHashMap<String, Object>();
properties.put( "name", "XR-51B" );
properties.put( "fuel", "Nutrinox" );
Entity user = em.create( "robot", properties );
assertNotNull( user );
app.waitForQueueDrainAndRefreshIndex();
assertNotNull( em.get( user.getUuid() ) );
}
@Test
public void testFilteringOfDuplicateEdges() throws Exception {
logger.info( "EntityManagerIT.testFilteringOfDuplicateEdges" );
EntityManager em = app.getEntityManager();
Map<String, Object> properties = new LinkedHashMap<String, Object>();
properties.put( "name", "fluffy1" );
Entity entity = em.create( "fluffy", properties );
EntityRef appRef = new SimpleEntityRef("application", app.getId());
EntityRef entityRef = new SimpleEntityRef(entity.getType(), entity.getUuid());
assertNotNull( entity );
// create duplicate edges
em.addToCollection(appRef, "fluffies", entityRef);
em.addToCollection(appRef, "fluffies", entityRef);
//app.waitForQueueDrainAndRefreshIndex();
Results results = em.getCollection(appRef,
"fluffies", null, 10, Level.ALL_PROPERTIES, true);
// we should be filtering duplicate edges so only assert 1 result back and not the # of edges
assertEquals(1, results.getEntities().size());
}
}