/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. 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. For additional information regarding
* copyright in this work, please see the NOTICE file in the top level
* directory of this distribution.
*/
package org.apache.usergrid.persistence.collection.mvcc.stage.write;
import com.datastax.driver.core.Session;
import com.google.inject.Inject;
import org.apache.usergrid.persistence.actorsystem.ActorSystemManager;
import org.apache.usergrid.persistence.collection.*;
import org.apache.usergrid.persistence.collection.exception.WriteUniqueVerifyException;
import org.apache.usergrid.persistence.collection.guice.TestCollectionModule;
import org.apache.usergrid.persistence.collection.mvcc.stage.TestEntityGenerator;
import org.apache.usergrid.persistence.collection.serialization.SerializationFig;
import org.apache.usergrid.persistence.collection.serialization.UniqueValue;
import org.apache.usergrid.persistence.collection.serialization.UniqueValueSerializationStrategy;
import org.apache.usergrid.persistence.collection.serialization.impl.UniqueValueImpl;
import org.apache.usergrid.persistence.collection.uniquevalues.UniqueValuesService;
import org.apache.usergrid.persistence.core.guice.MigrationManagerRule;
import org.apache.usergrid.persistence.core.scope.ApplicationScope;
import org.apache.usergrid.persistence.core.scope.ApplicationScopeImpl;
import org.apache.usergrid.persistence.core.test.ITRunner;
import org.apache.usergrid.persistence.core.test.UseModules;
import org.apache.usergrid.persistence.model.entity.Entity;
import org.apache.usergrid.persistence.model.entity.Id;
import org.apache.usergrid.persistence.model.entity.SimpleId;
import org.apache.usergrid.persistence.model.field.IntegerField;
import org.apache.usergrid.persistence.model.field.StringField;
import org.apache.usergrid.persistence.model.util.UUIDGenerator;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.Collections;
import static junit.framework.TestCase.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
/**
* Simple integration test of uniqueness verification.
*/
@RunWith( ITRunner.class )
@UseModules( TestCollectionModule.class )
public class WriteUniqueVerifyIT extends AbstractUniqueValueTest {
@Inject
private EntityCollectionManagerFactory factory;
@Inject
SerializationFig serializationFig;
@Inject
@Rule
public MigrationManagerRule migrationManagerRule;
@Inject
public UniqueValueSerializationStrategy uniqueValueSerializationStrategy;
@Inject
public EntityCollectionManagerFactory cmf;
@Inject
ActorSystemManager actorSystemManager;
@Inject
UniqueValuesService uniqueValuesService;
@Inject
Session session;
@Before
public void initAkka() {
// each test class needs unique port number
initAkka( 2553, actorSystemManager, uniqueValuesService );
}
@Test
public void testConflict() {
final Id appId = new SimpleId("testConflict");
final ApplicationScope scope = new ApplicationScopeImpl( appId );
final EntityCollectionManager entityManager = cmf.createCollectionManager( scope );
final Entity entity = TestEntityGenerator.generateEntity();
entity.setField(new StringField("name", "Aston Martin Vanquish", true));
entity.setField(new StringField("identifier", "v12", true));
entity.setField(new IntegerField("top_speed_mph", 200));
entityManager.write( entity, null ).toBlocking().last();
Entity entityFetched = entityManager.load( entity.getId() ).toBlocking().last();
entityFetched.setField( new StringField("foo", "bar"));
// wait for temporary unique value records to time out
try {
Thread.sleep(serializationFig.getTimeout() * 1100);
} catch (InterruptedException ignored) { }
// another enity that tries to use two unique values already taken by first
final Entity entity2 = TestEntityGenerator.generateEntity();
entity2.setField(new StringField("name", "Aston Martin Vanquish", true));
entity2.setField(new StringField("identifier", "v12", true));
entity2.setField(new IntegerField("top_speed_mph", 120));
try {
entityManager.write( entity2, null ).toBlocking().last();
fail("Write should have thrown an exception");
} catch ( Exception ex ) {
WriteUniqueVerifyException e = (WriteUniqueVerifyException)ex;
assertTrue( !e.getViolations().isEmpty() );
}
// ensure we can update original entity without error
entity.setField( new IntegerField("top_speed_mph", 190) );
entityManager.write( entity, null );
}
@Test
public void testNoConflict1() {
final Id appId = new SimpleId("testNoConflict");
final ApplicationScope scope = new ApplicationScopeImpl( appId);
final EntityCollectionManager entityManager = cmf.createCollectionManager( scope );
final Entity entity = TestEntityGenerator.generateEntity();
entity.setField(new StringField("name", "Porsche 911 GT3", true));
entity.setField(new StringField("identifier", "911gt3", true));
entity.setField(new IntegerField("top_speed_mph", 194));
entityManager.write( entity, null ).toBlocking().last();
Entity entityFetched = entityManager.load( entity.getId() ).toBlocking().last();
entityFetched.setField( new StringField("foo", "baz"));
entityManager.write( entityFetched, null ).toBlocking().last();
}
@Test
public void testNoConflict2() {
final Id appId = new SimpleId("testNoConflict");
final ApplicationScope scope = new ApplicationScopeImpl( appId );
final EntityCollectionManager entityManager = cmf.createCollectionManager( scope );
final Entity entity = TestEntityGenerator.generateEntity();
entity.setField(new StringField("name", "Alfa Romeo 8C Competizione", true));
entity.setField(new StringField("identifier", "ar8c", true));
entity.setField(new IntegerField("top_speed_mph", 182));
entityManager.write( entity, null ).toBlocking().last();
entity.setField( new StringField("foo", "bar"));
entityManager.write( entity, null ).toBlocking().last();
}
@Test
public void testConflictReadRepair() throws Exception {
final Id appId = new SimpleId("testNoConflict");
final ApplicationScope scope = new ApplicationScopeImpl( appId);
final EntityCollectionManager entityManager = cmf.createCollectionManager( scope );
final Entity entity = TestEntityGenerator.generateEntity();
entity.setField(new StringField("name", "Porsche 911 GT3", true));
entity.setField(new StringField("identifier", "911gt3", true));
entity.setField(new IntegerField("top_speed_mph", 194));
entityManager.write( entity, null ).toBlocking().last();
FieldSet fieldSet =
entityManager.getEntitiesFromFields("test", Collections.singletonList(entity.getField("name")), true)
.toBlocking().last();
MvccEntity entityFetched = fieldSet.getEntity( entity.getField("name") );
final Entity entityDuplicate = TestEntityGenerator.generateEntity();
UniqueValue uniqueValue = new UniqueValueImpl(new StringField("name", "Porsche 911 GT3", true),
entityDuplicate.getId(), UUIDGenerator.newTimeUUID());
// manually insert a record to simulate a 'duplicate' trying to be inserted
session.execute(uniqueValueSerializationStrategy.
writeCQL(scope, uniqueValue, -1));
FieldSet fieldSetAgain =
entityManager.getEntitiesFromFields("test", Collections.singletonList(entity.getField("name")), true)
.toBlocking().last();
MvccEntity entityFetchedAgain = fieldSetAgain.getEntity( entity.getField("name") );
assertEquals(entityFetched, entityFetchedAgain);
// now test writing the original entity again ( simulates a PUT )
// this should read repair and work
entityManager.write( entity, null ).toBlocking().last();
FieldSet fieldSetAgainAgain =
entityManager.getEntitiesFromFields("test", Collections.singletonList(entity.getField("name")), true)
.toBlocking().last();
MvccEntity entityFetchedAgainAgain = fieldSetAgainAgain.getEntity( entity.getField("name") );
assertEquals(entityFetched, entityFetchedAgainAgain);
}
}