package org.mongodb.morphia.optimisticlocks;
import org.bson.types.ObjectId;
import org.junit.Assert;
import org.junit.Test;
import org.mongodb.morphia.Datastore;
import org.mongodb.morphia.TestBase;
import org.mongodb.morphia.annotations.Entity;
import org.mongodb.morphia.annotations.Id;
import org.mongodb.morphia.annotations.Version;
import org.mongodb.morphia.mapping.MappedField;
import org.mongodb.morphia.mapping.validation.ConstraintViolationException;
import org.mongodb.morphia.query.Query;
import org.mongodb.morphia.query.UpdateOperations;
import org.mongodb.morphia.query.UpdateResults;
import org.mongodb.morphia.testutil.TestEntity;
import java.util.ConcurrentModificationException;
import static org.junit.Assert.assertEquals;
/**
* @author Uwe Schaefer, (us@thomas-daily.de)
*/
public class VersionTest extends TestBase {
@Test(expected = ConcurrentModificationException.class)
public void testConcurrentModDetection() throws Exception {
getMorphia().map(ALongPrimitive.class);
final ALongPrimitive a = new ALongPrimitive();
Assert.assertEquals(0, a.version);
getDs().save(a);
getDs().save(getDs().get(a));
getDs().save(a);
}
@Test(expected = ConcurrentModificationException.class)
public void testConcurrentModDetectionLong() throws Exception {
final ALong a = new ALong();
Assert.assertEquals(null, a.v);
getDs().save(a);
getDs().save(getDs().get(a));
getDs().save(a);
}
@Test(expected = ConcurrentModificationException.class)
public void testConcurrentModDetectionLongWithMerge() throws Exception {
final ALong a = new ALong();
Assert.assertEquals(null, a.v);
getDs().save(a);
a.text = " foosdfds ";
final ALong a2 = getDs().get(a);
getDs().save(a2);
getDs().merge(a);
}
@Test(expected = ConstraintViolationException.class)
public void testInvalidVersionUse() throws Exception {
getMorphia().map(InvalidVersionUse.class);
}
@Test
public void testVersionFieldNameContribution() throws Exception {
final MappedField mappedFieldByJavaField = getMorphia().getMapper().getMappedClass(ALong.class).getMappedFieldByJavaField("v");
Assert.assertEquals("versionNameContributedByAnnotation", mappedFieldByJavaField.getNameToStore());
}
@Test
public void testVersionInHashcode() throws Exception {
getMorphia().mapPackage("com.example");
final VersionInHashcode model = new VersionInHashcode();
model.data = "whatever";
getDs().save(model);
Assert.assertNotNull(model.version);
}
@Test
public void testVersions() throws Exception {
final ALongPrimitive a = new ALongPrimitive();
Assert.assertEquals(0, a.version);
getDs().save(a);
Assert.assertTrue(a.version > 0);
final long version1 = a.version;
getDs().save(a);
Assert.assertTrue(a.version > 0);
final long version2 = a.version;
Assert.assertFalse(version1 == version2);
}
@Test
public void testVersionsWithFindAndModify() {
final ALongPrimitive initial = new ALongPrimitive();
Datastore ds = getDs();
ds.save(initial);
Query<ALongPrimitive> query = ds.find(ALongPrimitive.class)
.field("id").equal(initial.getId());
UpdateOperations<ALongPrimitive> update = ds.createUpdateOperations(ALongPrimitive.class)
.set("text", "some new value");
ALongPrimitive postUpdate = ds.findAndModify(query, update);
Assert.assertEquals(initial.version + 1, postUpdate.version);
}
@Test
public void testVersionsWithUpdate() {
final ALongPrimitive initial = new ALongPrimitive();
Datastore ds = getDs();
ds.save(initial);
Query<ALongPrimitive> query = ds.find(ALongPrimitive.class)
.field("id").equal(initial.getId());
UpdateOperations<ALongPrimitive> update = ds.createUpdateOperations(ALongPrimitive.class)
.set("text", "some new value");
UpdateResults results = ds.update(query, update);
assertEquals(1, results.getUpdatedCount());
ALongPrimitive postUpdate = ds.get(ALongPrimitive.class, initial.getId());
Assert.assertEquals(initial.version + 1, postUpdate.version);
}
@Entity
public static class VersionInHashcode {
@Id
private ObjectId id;
@Version
private Long version;
private String data;
@Override
public int hashCode() {
final int dataHashCode = (data == null) ? 0 : data.hashCode();
final int versionHashCode = (version == null) ? 0 : version.hashCode();
return dataHashCode + versionHashCode;
}
}
public static class ALongPrimitive extends TestEntity {
@Version
private long version;
private String text;
public long getVersion() {
return version;
}
public void setVersion(final long version) {
this.version = version;
}
public String getText() {
return text;
}
public void setText(final String text) {
this.text = text;
}
}
public static class ALong extends TestEntity {
@Version("versionNameContributedByAnnotation")
private Long v;
private String text;
}
@Entity
static class InvalidVersionUse {
@Id
private String id;
@Version
private long version1;
@Version
private long version2;
}
}