/*
* Copyright 2016 Realm Inc.
*
* 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 io.realm;
import android.content.Context;
import android.os.Build;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.IOException;
import java.util.Date;
import io.realm.entities.AllTypes;
import io.realm.entities.pojo.AllTypesRealmModel;
import io.realm.entities.pojo.InvalidRealmModel;
import io.realm.entities.pojo.PojoWithRealmListOfRealmObject;
import io.realm.entities.pojo.RealmModelWithRealmListOfRealmModel;
import io.realm.entities.pojo.RealmModelWithRealmModelField;
import io.realm.entities.pojo.RealmObjectWithRealmListOfRealmModel;
import io.realm.entities.pojo.RealmObjectWithRealmModelField;
import io.realm.exceptions.RealmException;
import io.realm.rule.RunInLooperThread;
import io.realm.rule.RunTestInLooperThread;
import io.realm.rule.TestRealmConfigurationFactory;
import static io.realm.internal.test.ExtraTests.assertArrayEquals;
import static org.hamcrest.number.OrderingComparison.greaterThanOrEqualTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeThat;
// Tests API methods when using a model class implementing RealmModel instead
// of extending RealmObject.
@RunWith(AndroidJUnit4.class)
public class RealmModelTests {
private final static int TEST_DATA_SIZE = 10;
private Context context;
private Realm realm;
@Rule
public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();
@Rule
public final RunInLooperThread looperThread = new RunInLooperThread();
@Before
public void setUp() {
// Injecting the Instrumentation instance is required
// for your test to run with AndroidJUnitRunner.
context = InstrumentationRegistry.getInstrumentation().getContext();
RealmConfiguration realmConfig = configFactory.createConfiguration();
realm = Realm.getInstance(realmConfig);
}
@After
public void tearDown() {
if (realm != null) {
realm.close();
}
}
private void populateTestRealm(Realm realm, int objects) {
realm.beginTransaction();
realm.delete(AllTypesRealmModel.class);
for (int i = 0; i < objects; ++i) {
AllTypesRealmModel allTypes = new AllTypesRealmModel();
allTypes.columnLong = i;
allTypes.columnBoolean = (i % 3) == 0;
allTypes.columnBinary = new byte[]{1, 2, 3};
allTypes.columnDate = new Date();
allTypes.columnDouble = Math.PI + i;
allTypes.columnFloat = 1.234567f;
allTypes.columnString = "test data ";
allTypes.columnByte = 0x2A;
realm.copyToRealm(allTypes);
}
realm.commitTransaction();
}
@Test
public void createObject() {
for (int i = 1; i < 43; i++) { // Using i = 0 as PK will crash subsequent createObject
// since createObject uses default values.
realm.beginTransaction();
realm.createObject(AllTypesRealmModel.class, i);
realm.commitTransaction();
}
long size = realm.where(AllTypesRealmModel.class).count();
assertEquals("Realm.get is returning wrong result set", 42, size);
}
@Test
public void copyToRealm() {
populateTestRealm(realm, TEST_DATA_SIZE);
long size = realm.where(AllTypesRealmModel.class).count();
assertEquals("Realm.get is returning wrong result set", TEST_DATA_SIZE, size);
}
@Test
public void copyFromRealm() {
populateTestRealm(realm, TEST_DATA_SIZE);
AllTypesRealmModel realmObject = realm.where(AllTypesRealmModel.class).findAllSorted(AllTypesRealmModel.FIELD_LONG).first();
AllTypesRealmModel unmanagedObject = realm.copyFromRealm(realmObject);
assertArrayEquals(realmObject.columnBinary, unmanagedObject.columnBinary);
assertEquals(realmObject.columnString, unmanagedObject.columnString);
assertEquals(realmObject.columnLong, unmanagedObject.columnLong);
assertEquals(realmObject.columnFloat, unmanagedObject.columnFloat, 0.00000000001);
assertEquals(realmObject.columnDouble, unmanagedObject.columnDouble, 0.00000000001);
assertEquals(realmObject.columnBoolean, unmanagedObject.columnBoolean);
assertEquals(realmObject.columnDate, unmanagedObject.columnDate);
assertEquals(realmObject.hashCode(), unmanagedObject.hashCode());
}
@Test
public void copyToRealmOrUpdate() {
realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
AllTypesRealmModel obj = new AllTypesRealmModel();
obj.columnLong = 1;
realm.copyToRealm(obj);
AllTypesRealmModel obj2 = new AllTypesRealmModel();
obj2.columnLong = 1;
obj2.columnString = "Foo";
realm.copyToRealmOrUpdate(obj2);
}
});
assertEquals(1, realm.where(AllTypesRealmModel.class).count());
AllTypesRealmModel obj = realm.where(AllTypesRealmModel.class).findFirst();
assertNotNull(obj);
assertEquals("Foo", obj.columnString);
}
@Test
public void createOrUpdateAllFromJson() throws IOException {
assumeThat(Build.VERSION.SDK_INT, greaterThanOrEqualTo(Build.VERSION_CODES.HONEYCOMB));
realm.beginTransaction();
realm.createOrUpdateAllFromJson(AllTypesRealmModel.class, TestHelper.loadJsonFromAssets(context, "list_alltypes_primarykey.json"));
realm.commitTransaction();
assertEquals(1, realm.where(AllTypesRealmModel.class).count());
AllTypesRealmModel obj = realm.where(AllTypesRealmModel.class).findFirst();
assertNotNull(obj);
assertEquals("Bar", obj.columnString);
assertEquals(2.23F, obj.columnFloat, 0.000000001);
assertEquals(2.234D, obj.columnDouble, 0.000000001);
assertEquals(true, obj.columnBoolean);
assertArrayEquals(new byte[]{1, 2, 3}, obj.columnBinary);
assertEquals(new Date(2000), obj.columnDate);
assertEquals("Dog4", obj.columnRealmObject.getName());
assertEquals(2, obj.columnRealmList.size());
assertEquals("Dog5", obj.columnRealmList.get(0).getName());
}
// 'where' with filed selection.
@Test
public void query() {
populateTestRealm(realm, TEST_DATA_SIZE);
assertEquals(5, realm.where(AllTypesRealmModel.class).greaterThanOrEqualTo(AllTypesRealmModel.FIELD_DOUBLE, 8.1415).count());
}
// Async where with filed selection.
@Test
@RunTestInLooperThread
public void async_query() {
Realm realm = looperThread.getRealm();
populateTestRealm(realm, TEST_DATA_SIZE);
final RealmResults<AllTypesRealmModel> allTypesRealmModels = realm.where(AllTypesRealmModel.class).distinctAsync(AllTypesRealmModel.FIELD_STRING);
looperThread.keepStrongReference(allTypesRealmModels);
allTypesRealmModels.addChangeListener(new RealmChangeListener<RealmResults<AllTypesRealmModel>>() {
@Override
public void onChange(RealmResults<AllTypesRealmModel> object) {
assertEquals(1, allTypesRealmModels.size());
looperThread.testComplete();
}
});
}
@Test
public void dynamicObject() {
populateTestRealm(realm, TEST_DATA_SIZE);
AllTypesRealmModel typedObj = realm.where(AllTypesRealmModel.class).findFirst();
assertNotNull(typedObj);
DynamicRealmObject dObj = new DynamicRealmObject(typedObj);
realm.beginTransaction();
dObj.setByte(AllTypesRealmModel.FIELD_BYTE, (byte) 42);
assertEquals(42, dObj.getLong(AllTypesRealmModel.FIELD_BYTE));
assertEquals(42, typedObj.columnByte);
dObj.setBlob(AllTypesRealmModel.FIELD_BINARY, new byte[]{1, 2, 3});
Assert.assertArrayEquals(new byte[]{1, 2, 3}, dObj.getBlob(AllTypesRealmModel.FIELD_BINARY));
Assert.assertArrayEquals(new byte[]{1, 2, 3}, typedObj.columnBinary);
realm.cancelTransaction();
}
@Test
@RunTestInLooperThread
public void dynamicRealm() {
populateTestRealm(looperThread.getRealm(), TEST_DATA_SIZE);
final DynamicRealm dynamicRealm = DynamicRealm.getInstance(looperThread.getConfiguration());
dynamicRealm.beginTransaction();
DynamicRealmObject dog = dynamicRealm.createObject(AllTypesRealmModel.CLASS_NAME, 42);
assertEquals(42, dog.getLong(AllTypesRealmModel.FIELD_LONG));
dynamicRealm.commitTransaction();
RealmResults<DynamicRealmObject> allAsync = dynamicRealm.where(AllTypesRealmModel.CLASS_NAME).equalTo(AllTypesRealmModel.FIELD_LONG, 42).findAll();
allAsync.load();
assertTrue(allAsync.isLoaded());
assertEquals(1, allAsync.size());
dynamicRealm.beginTransaction();
allAsync.deleteAllFromRealm();
dynamicRealm.commitTransaction();
RealmResults<DynamicRealmObject> results = dynamicRealm.where(AllTypesRealmModel.CLASS_NAME).findAll();
assertEquals(TEST_DATA_SIZE, results.size());
for (int i = 0; i < TEST_DATA_SIZE; i++) {
assertEquals(Math.PI + i, results.get(i).getDouble(AllTypesRealmModel.FIELD_DOUBLE), 0.0000001);
assertEquals((i % 3) == 0, results.get(i).getBoolean(AllTypesRealmModel.FIELD_BOOLEAN));
}
dynamicRealm.close();
looperThread.testComplete();
}
// Exception expected when using in schema model not annotated.
// A valid model need to implement the interface RealmModel and annotate the class with @RealmClass.
// We expect in this test a runtime exception 'InvalidRealmModel is not part of the schema for this Realm.'.
@Test(expected = RealmException.class)
public void invalidModelDefinition() {
realm.beginTransaction();
realm.createObject(InvalidRealmModel.class);
realm.commitTransaction();
}
// Tests the behaviour of a RealmModel, containing a RealmList
// of other RealmModel, in managed and unmanaged mode.
@Test
public void realmModelWithRealmListOfRealmModel() {
RealmList<AllTypesRealmModel> allTypesRealmModels = new RealmList<AllTypesRealmModel>();
AllTypesRealmModel allTypePojo;
for (int i = 0; i < 10; i++) {
allTypePojo = new AllTypesRealmModel();
allTypePojo.columnLong = i;
allTypesRealmModels.add(allTypePojo);
}
AllTypesRealmModel pojo1 = allTypesRealmModels.get(1);
assertEquals(1, pojo1.columnLong);
allTypesRealmModels.move(1, 0);
assertEquals(0, allTypesRealmModels.indexOf(pojo1));
RealmModelWithRealmListOfRealmModel model = new RealmModelWithRealmListOfRealmModel();
model.setColumnRealmList(allTypesRealmModels);
realm.beginTransaction();
realm.copyToRealm(model);
realm.commitTransaction();
RealmResults<RealmModelWithRealmListOfRealmModel> all = realm.where(RealmModelWithRealmListOfRealmModel.class).findAll();
assertEquals(1, all.size());
assertEquals(10, all.first().getColumnRealmList().size());
assertEquals(1, all.first().getColumnRealmList().first().columnLong);
}
// Tests the behaviour of a RealmModel, containing a RealmList
// of RealmObject, in managed and unmanaged mode.
@Test
public void realmModelWithRealmListOfRealmObject() {
RealmList<AllTypes> allTypes = new RealmList<AllTypes>();
AllTypes allType;
for (int i = 0; i < 10; i++) {
allType = new AllTypes();
allType.setColumnLong(i);
allTypes.add(allType);
}
AllTypes pojo1 = allTypes.get(1);
assertEquals(1, pojo1.getColumnLong());
allTypes.move(1, 0);
assertEquals(0, allTypes.indexOf(pojo1));
PojoWithRealmListOfRealmObject model = new PojoWithRealmListOfRealmObject();
model.setColumnRealmList(allTypes);
realm.beginTransaction();
realm.copyToRealm(model);
realm.commitTransaction();
RealmResults<PojoWithRealmListOfRealmObject> all = realm.where(PojoWithRealmListOfRealmObject.class).findAll();
assertEquals(1, all.size());
assertEquals(10, all.first().getColumnRealmList().size());
assertEquals(1, all.first().getColumnRealmList().first().getColumnLong());
}
// Tests the behaviour of a RealmObject, containing a RealmList
// of RealmModel, in managed and unmanaged mode.
@Test
public void realmObjectWithRealmListOfRealmModel() {
RealmList<AllTypesRealmModel> allTypesRealmModel = new RealmList<AllTypesRealmModel>();
AllTypesRealmModel allTypePojo;
for (int i = 0; i < 10; i++) {
allTypePojo = new AllTypesRealmModel();
allTypePojo.columnLong = i;
allTypesRealmModel.add(allTypePojo);
}
AllTypesRealmModel pojo1 = allTypesRealmModel.get(1);
assertEquals(1, pojo1.columnLong);
allTypesRealmModel.move(1, 0);
assertEquals(0, allTypesRealmModel.indexOf(pojo1));
RealmObjectWithRealmListOfRealmModel model = new RealmObjectWithRealmListOfRealmModel();
model.setColumnRealmList(allTypesRealmModel);
realm.beginTransaction();
realm.copyToRealm(model);
realm.commitTransaction();
RealmResults<RealmObjectWithRealmListOfRealmModel> all = realm.where(RealmObjectWithRealmListOfRealmModel.class).findAll();
assertEquals(1, all.size());
assertEquals(10, all.first().getColumnRealmList().size());
assertEquals(1, all.first().getColumnRealmList().first().columnLong);
}
// Tests the behaviour of a RealmModel, containing a RealmModel field.
@Test
public void realmModelWithRealmModelField() {
RealmModelWithRealmModelField realmModelWithRealmModelField = new RealmModelWithRealmModelField();
AllTypesRealmModel allTypePojo = new AllTypesRealmModel();
allTypePojo.columnLong = 42;
realmModelWithRealmModelField.setAllTypesRealmModel(allTypePojo);
realm.beginTransaction();
realm.copyToRealm(realmModelWithRealmModelField);
realm.commitTransaction();
RealmResults<RealmModelWithRealmModelField> all = realm.where(RealmModelWithRealmModelField.class).findAll();
assertEquals(1, all.size());
assertEquals(42, all.first().getAllTypesRealmModel().columnLong);
}
// Tests the behaviour of a RealmObject, containing a RealmModel field.
@Test
public void realmObjectWithRealmModelField() {
RealmObjectWithRealmModelField realmObjectWithRealmModelField = new RealmObjectWithRealmModelField();
AllTypesRealmModel allTypePojo = new AllTypesRealmModel();
allTypePojo.columnLong = 42;
realmObjectWithRealmModelField.setAllTypesRealmModel(allTypePojo);
realm.beginTransaction();
realm.copyToRealm(realmObjectWithRealmModelField);
realm.commitTransaction();
RealmResults<RealmObjectWithRealmModelField> all = realm.where(RealmObjectWithRealmModelField.class).findAll();
assertEquals(1, all.size());
assertEquals(42, all.first().getAllTypesRealmModel().columnLong);
}
}