/*
* Copyright 2015 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 org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import android.test.MoreAsserts;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.Set;
import io.realm.entities.AllTypes;
import io.realm.entities.AllTypesPrimaryKey;
import io.realm.entities.AnimalModule;
import io.realm.entities.AssetFileModule;
import io.realm.entities.Cat;
import io.realm.entities.CatOwner;
import io.realm.entities.CyclicType;
import io.realm.entities.Dog;
import io.realm.entities.HumanModule;
import io.realm.entities.Owner;
import io.realm.exceptions.RealmException;
import io.realm.exceptions.RealmFileException;
import io.realm.exceptions.RealmMigrationNeededException;
import io.realm.internal.modules.CompositeMediator;
import io.realm.internal.modules.FilterableMediator;
import io.realm.rule.TestRealmConfigurationFactory;
import io.realm.rx.RealmObservableFactory;
import io.realm.rx.RxObservableFactory;
import rx.Observable;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@RunWith(AndroidJUnit4.class)
public class RealmConfigurationTests {
@Rule
public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();
@Rule
public final ExpectedException thrown = ExpectedException.none();
private Context context;
private RealmConfiguration defaultConfig;
private Realm realm;
@Before
public void setUp() {
context = InstrumentationRegistry.getTargetContext();
defaultConfig = configFactory.createConfiguration();
}
@After
public void tearDown() throws Exception {
if (realm != null) {
realm.close();
}
}
private void clearDefaultConfiguration() throws NoSuchFieldException, IllegalAccessException {
final Field field = Realm.class.getDeclaredField("defaultConfiguration");
field.setAccessible(true);
field.set(null, null);
}
@Test
public void setDefaultConfiguration_nullThrows() throws NoSuchFieldException, IllegalAccessException {
clearDefaultConfiguration();
try {
Realm.setDefaultConfiguration(null);
fail();
} catch (IllegalArgumentException ignored) {
}
}
@Test
public void getInstance_nullConfigThrows() {
try {
Realm.getInstance((RealmConfiguration) null);
fail();
} catch (IllegalArgumentException ignored) {
}
}
@Test
public void constructBuilder_nullNameThrows() {
try {
new RealmConfiguration.Builder(context).name(null);
fail();
} catch (IllegalArgumentException ignored) {
}
}
@Test
public void constructBuilder_emptyNameThrows() {
try {
new RealmConfiguration.Builder(context).name("");
fail();
} catch (IllegalArgumentException ignored) {
}
}
@Test(expected = IllegalArgumentException.class)
public void directory_null() {
new RealmConfiguration.Builder(context).directory(null);
}
@Test
public void directory_writeProtectedDir() {
File dir = new File("/");
thrown.expect(IllegalArgumentException.class);
new RealmConfiguration.Builder(context).directory(dir);
}
@Test
public void directory_dirIsAFile() throws IOException {
File dir = configFactory.getRoot();
File file = new File(dir, "dummyfile");
assertTrue(file.createNewFile());
thrown.expect(IllegalArgumentException.class);
new RealmConfiguration.Builder(context).directory(file);
}
@Test
public void getInstance_idForHashCollision() {
// Ea.hashCode() == FB.hashCode()
RealmConfiguration configA = configFactory.createConfiguration("Ea");
RealmConfiguration configB = configFactory.createConfiguration("FB");
Realm r1 = Realm.getInstance(configA);
Realm r2 = Realm.getInstance(configB);
assertNotSame(r1, r2);
r1.close();
r2.close();
}
@Test
public void constructBuilder_nullKeyThrows() {
try {
new RealmConfiguration.Builder(context).encryptionKey(null);
fail();
} catch (IllegalArgumentException ignored) {
}
}
@Test
public void constructBuilder_wrongKeyLengthThrows() {
byte[][] wrongKeys = new byte[][] {
new byte[0],
new byte[RealmConfiguration.KEY_LENGTH - 1],
new byte[RealmConfiguration.KEY_LENGTH + 1]
};
for (byte[] key : wrongKeys) {
try {
new RealmConfiguration.Builder(context).encryptionKey(key);
fail("Key with length " + key.length + " should throw an exception");
} catch (IllegalArgumentException ignored) {
}
}
}
@Test
public void constructBuilder_negativeVersionThrows() {
try {
new RealmConfiguration.Builder(context).schemaVersion(-1);
fail();
} catch (IllegalArgumentException ignored) {
}
}
@Test
public void constructBuilder_versionLessThanDiscVersionThrows() {
realm = Realm.getInstance(new RealmConfiguration.Builder(context)
.directory(configFactory.getRoot())
.schemaVersion(42)
.build());
realm.close();
int[] wrongVersions = new int[] { 0, 1, 41 };
for (int version : wrongVersions) {
try {
realm = Realm.getInstance(new RealmConfiguration.Builder(context)
.directory(configFactory.getRoot())
.schemaVersion(version)
.build());
fail("Version " + version + " should throw an exception");
} catch (IllegalArgumentException ignored) {
}
}
}
@Test
public void constructBuilder_versionEqualWhenSchemaChangesThrows() {
// Creates initial Realm.
RealmConfiguration config = new RealmConfiguration.Builder(context)
.directory(configFactory.getRoot())
.schemaVersion(42)
.schema(Dog.class)
.build();
Realm.getInstance(config).close();
// Creates new instance with a configuration containing another schema.
try {
config = new RealmConfiguration.Builder(context)
.directory(configFactory.getRoot())
.schemaVersion(42)
.schema(AllTypesPrimaryKey.class)
.build();
realm = Realm.getInstance(config);
fail("A migration should be required");
} catch (RealmMigrationNeededException ignored) {
}
}
@Test
public void customSchemaDontIncludeLinkedClasses() {
RealmConfiguration config = new RealmConfiguration.Builder(context)
.directory(configFactory.getRoot())
.schema(Dog.class)
.build();
realm = Realm.getInstance(config);
try {
assertEquals(3, realm.getTable(Owner.class).getColumnCount());
fail("Owner should to be part of the schema");
} catch (IllegalArgumentException ignored) {
}
}
@Test
public void migration_nullThrows() {
try {
new RealmConfiguration.Builder(context).migration(null).build();
fail();
} catch (IllegalArgumentException ignored) {
}
}
@Test
public void modules_nonRealmModulesThrows() {
// Tests first argument.
try {
new RealmConfiguration.Builder(context).modules(new Object());
fail();
} catch (IllegalArgumentException ignored) {
}
// Tests second argument.
try {
new RealmConfiguration.Builder(context).modules(Realm.getDefaultModule(), new Object());
fail();
} catch (IllegalArgumentException ignored) {
}
}
@Test
public void modules() {
RealmConfiguration realmConfig = new RealmConfiguration.Builder(context)
.directory(configFactory.getRoot())
.modules(Realm.getDefaultModule(), (Object) null)
.build();
realm = Realm.getInstance(realmConfig);
assertNotNull(realm.getTable(AllTypes.class));
}
@Test
public void setDefaultConfiguration() throws NoSuchFieldException, IllegalAccessException {
clearDefaultConfiguration();
Realm.setDefaultConfiguration(defaultConfig);
realm = Realm.getDefaultInstance();
assertEquals(realm.getPath(), defaultConfig.getPath());
}
@Test
public void getInstance() {
realm = Realm.getInstance(defaultConfig);
assertEquals(realm.getPath(), defaultConfig.getPath());
}
@Test
public void standardSetup() {
RealmConfiguration config = new RealmConfiguration.Builder(context)
.directory(configFactory.getRoot())
.name("foo.realm")
.encryptionKey(TestHelper.getRandomKey())
.schemaVersion(42)
.migration(new RealmMigration() {
@Override
public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {
// no-op
}
})
.deleteRealmIfMigrationNeeded()
.build();
Realm.deleteRealm(config);
realm = Realm.getInstance(config);
assertTrue(realm.getPath().endsWith("foo.realm"));
assertEquals(42, realm.getVersion());
}
@Test
public void deleteRealmIfMigrationNeeded() {
// Populates v0 of a Realm with an object.
RealmConfiguration config = new RealmConfiguration.Builder(context)
.directory(configFactory.getRoot())
.schema(Dog.class)
.schemaVersion(0)
.build();
Realm.deleteRealm(config);
realm = Realm.getInstance(config);
realm.beginTransaction();
realm.copyToRealm(new Dog("Foo"));
realm.commitTransaction();
assertEquals(1, realm.where(Dog.class).count());
realm.close();
// Changes schema and verifies that Realm has been cleared.
config = new RealmConfiguration.Builder(context)
.directory(configFactory.getRoot())
.schema(Owner.class, Dog.class)
.schemaVersion(1)
.deleteRealmIfMigrationNeeded()
.build();
realm = Realm.getInstance(config);
assertEquals(0, realm.where(Dog.class).count());
}
@Test
public void deleteRealmIfMigrationNeeded_failsWhenAssetFileProvided() {
Context context = InstrumentationRegistry.getInstrumentation().getContext();
// Has a builder instance to isolate codepath.
RealmConfiguration.Builder builder = new RealmConfiguration.Builder(context);
try {
builder
.assetFile("asset_file.realm")
.deleteRealmIfMigrationNeeded();
fail();
} catch (IllegalStateException expected) {
assertEquals("Realm cannot clear its schema when previously configured to use an asset file by calling assetFile().",
expected.getMessage());
}
}
@Test
public void upgradeVersionWithNoMigration() {
realm = Realm.getInstance(defaultConfig);
assertEquals(0, realm.getVersion());
realm.close();
// Version upgrades should always require a migration.
try {
realm = Realm.getInstance(new RealmConfiguration.Builder(context)
.directory(configFactory.getRoot())
.schemaVersion(42)
.build());
fail();
} catch (RealmMigrationNeededException expected) {
// And it should come with a cause.
assertEquals("Realm on disk need to migrate from v0 to v42", expected.getMessage());
}
}
@Test
public void equals() {
RealmConfiguration config1 = new RealmConfiguration.Builder(context).build();
RealmConfiguration config2 = new RealmConfiguration.Builder(context).build();
assertTrue(config1.equals(config2));
}
@Test
public void equals_respectReadOnly() {
RealmConfiguration config1 = new RealmConfiguration.Builder(context).assetFile("foo").build();
RealmConfiguration config2 = new RealmConfiguration.Builder(context).assetFile("foo").readOnly().build();
assertFalse(config1.equals(config2));
}
@Test
public void equalsWhenRxJavaUnavailable() {
// Test for https://github.com/realm/realm-java/issues/2416
RealmConfiguration config1 = new RealmConfiguration.Builder(context).directory(configFactory.getRoot()).build();
TestHelper.emulateRxJavaUnavailable(config1);
RealmConfiguration config2 = new RealmConfiguration.Builder(context).directory(configFactory.getRoot()).build();
TestHelper.emulateRxJavaUnavailable(config2);
assertTrue(config1.equals(config2));
}
@Test
public void hashCode_Test() {
RealmConfiguration config1 = new RealmConfiguration.Builder(context).directory(configFactory.getRoot()).build();
RealmConfiguration config2 = new RealmConfiguration.Builder(context).directory(configFactory.getRoot()).build();
assertEquals(config1.hashCode(), config2.hashCode());
}
@Test
public void equals_withCustomModules() {
RealmConfiguration config1 = new RealmConfiguration.Builder(context)
.directory(configFactory.getRoot())
.modules(new HumanModule(), new AnimalModule())
.build();
RealmConfiguration config2 = new RealmConfiguration.Builder(context)
.directory(configFactory.getRoot())
.modules(new AnimalModule(), new HumanModule())
.build();
assertTrue(config1.equals(config2));
}
@Test
public void hashCode_withCustomModules() {
RealmConfiguration config1 = new RealmConfiguration.Builder(context)
.directory(configFactory.getRoot())
.modules(new HumanModule(), new AnimalModule())
.build();
RealmConfiguration config2 = new RealmConfiguration.Builder(context)
.directory(configFactory.getRoot())
.modules(new AnimalModule(), new HumanModule())
.build();
assertEquals(config1.hashCode(), config2.hashCode());
}
@Test
public void hashCode_withDifferentRxObservableFactory() {
RealmConfiguration config1 = new RealmConfiguration.Builder(context)
.directory(configFactory.getRoot())
.rxFactory(new RealmObservableFactory())
.build();
RealmConfiguration config2 = new RealmConfiguration.Builder(context)
.directory(configFactory.getRoot())
.rxFactory(new RealmObservableFactory() {
@Override
public int hashCode() {
return super.hashCode() + 1;
}
})
.build();
assertNotEquals(config1.hashCode(), config2.hashCode());
}
@Test
public void equals_configurationsReturnCachedRealm() {
Realm realm1 = Realm.getInstance(new RealmConfiguration.Builder(context).directory(configFactory.getRoot()).build());
Realm realm2 = Realm.getInstance(new RealmConfiguration.Builder(context).directory(configFactory.getRoot()).build());
try {
assertEquals(realm1, realm2);
} finally {
realm1.close();
realm2.close();
}
}
@Test
public void schemaVersion_differentVersionsThrows() {
RealmConfiguration config1 = new RealmConfiguration.Builder(context).directory(configFactory.getRoot()).schemaVersion(1).build();
RealmConfiguration config2 = new RealmConfiguration.Builder(context).directory(configFactory.getRoot()).schemaVersion(2).build();
Realm realm1 = Realm.getInstance(config1);
try {
Realm.getInstance(config2);
fail();
} catch (IllegalArgumentException ignored) {
} finally {
realm1.close();
}
}
@Test
public void encryptionKey_differentEncryptionKeysThrows() {
RealmConfiguration config1 = new RealmConfiguration.Builder(context)
.directory(configFactory.getRoot())
.encryptionKey(TestHelper.getRandomKey())
.build();
RealmConfiguration config2 = new RealmConfiguration.Builder(context)
.directory(configFactory.getRoot())
.encryptionKey(TestHelper.getRandomKey())
.build();
Realm realm1 = Realm.getInstance(config1);
try {
realm = Realm.getInstance(config2);
fail();
} catch (IllegalArgumentException ignored) {
} finally {
realm1.close();
}
}
@Test
public void schema_differentSchemasThrows() {
RealmConfiguration config1 = new RealmConfiguration.Builder(context)
.directory(configFactory.getRoot())
.schema(AllTypes.class)
.build();
RealmConfiguration config2 = new RealmConfiguration.Builder(context)
.directory(configFactory.getRoot())
.schema(CyclicType.class).build();
Realm realm1 = Realm.getInstance(config1);
try {
Realm.getInstance(config2);
fail();
} catch (IllegalArgumentException ignored) {
} finally {
realm1.close();
}
}
// Creates Realm instances with same name but different durabilities is not allowed.
@Test
public void inMemory_differentDurabilityThrows() {
RealmConfiguration config1 = new RealmConfiguration.Builder(context)
.directory(configFactory.getRoot())
.inMemory()
.build();
RealmConfiguration config2 = new RealmConfiguration.Builder(context)
.directory(configFactory.getRoot())
.build();
// Creates In-memory Realm first.
Realm realm1 = Realm.getInstance(config1);
try {
// On-disk Realm then. Not allowed!
Realm.getInstance(config2);
fail();
} catch (IllegalArgumentException ignored) {
} finally {
realm1.close();
}
// Creates on-disk Realm first.
realm1 = Realm.getInstance(config2);
try {
// In-memory Realm then. Not allowed!
Realm.getInstance(config1);
fail();
} catch (IllegalArgumentException ignored) {
} finally {
realm1.close();
}
}
// It is allowed to create multiple Realm with same name but in different directory.
@Test
public void constructBuilder_differentDirSameName() throws IOException {
RealmConfiguration config1 = new RealmConfiguration.Builder(context).directory(configFactory.getRoot()).build();
RealmConfiguration config2 = new RealmConfiguration.Builder(context).directory(configFactory.newFolder()).build();
Realm realm1 = Realm.getInstance(config1);
Realm realm2 = Realm.getInstance(config2);
realm1.close();
realm2.close();
}
@Test
public void encryptionKey_keyStorage() throws Exception {
// Generates a key and uses it in a RealmConfiguration.
byte[] oldKey = TestHelper.getRandomKey(12345);
byte[] key = oldKey;
RealmConfiguration config = new RealmConfiguration.Builder(context)
.directory(configFactory.getRoot())
.encryptionKey(key)
.build();
// Generates a different key and assigns it to the same variable.
byte[] newKey = TestHelper.getRandomKey(67890);
MoreAsserts.assertNotEqual(key, newKey);
key = newKey;
MoreAsserts.assertEquals(key, newKey);
// Ensures that the stored key did not change.
MoreAsserts.assertEquals(oldKey, config.getEncryptionKey());
}
@Test
public void modelClassesForDefaultMediator() throws Exception {
assertTrue(defaultConfig.getSchemaMediator() instanceof DefaultRealmModuleMediator);
final Set<Class<? extends RealmModel>> realmClasses = defaultConfig.getRealmObjectClasses();
assertTrue(realmClasses.contains(AllTypes.class));
// Tests returned Set is unmodifiable.
try {
realmClasses.add(AllTypes.class);
fail();
} catch (UnsupportedOperationException ignored) {
}
}
@Test
public void modelClasses_forGeneratedMediator() throws Exception {
final RealmConfiguration config = new RealmConfiguration.Builder(context)
.directory(configFactory.getRoot())
.modules(new HumanModule())
.build();
assertTrue(config.getSchemaMediator() instanceof HumanModuleMediator);
final Set<Class<? extends RealmModel>> realmClasses = config.getRealmObjectClasses();
assertFalse(realmClasses.contains(AllTypes.class));
assertTrue(realmClasses.contains(CatOwner.class));
assertFalse(realmClasses.contains(Cat.class));
// Tests returned Set is unmodifiable.
try {
realmClasses.add(AllTypes.class);
fail();
} catch (UnsupportedOperationException ignored) {
}
}
@Test
public void modelClasses_forCompositeMediator() throws Exception {
final RealmConfiguration config = new RealmConfiguration.Builder(context)
.directory(configFactory.getRoot())
.modules(new HumanModule(), new AnimalModule())
.build();
assertTrue(config.getSchemaMediator() instanceof CompositeMediator);
final Set<Class<? extends RealmModel>> realmClasses = config.getRealmObjectClasses();
assertFalse(realmClasses.contains(AllTypes.class));
assertTrue(realmClasses.contains(CatOwner.class));
assertTrue(realmClasses.contains(Cat.class));
// Tests returned Set is unmodifiable.
try {
realmClasses.add(AllTypes.class);
fail();
} catch (UnsupportedOperationException ignored) {
}
}
@Test
public void modelClasses_forFilterableMediator() throws Exception {
//noinspection unchecked
final RealmConfiguration config = new RealmConfiguration.Builder(context)
.directory(configFactory.getRoot())
.schema(AllTypes.class, CatOwner.class)
.build();
assertTrue(config.getSchemaMediator() instanceof FilterableMediator);
final Set<Class<? extends RealmModel>> realmClasses = config.getRealmObjectClasses();
assertTrue(realmClasses.contains(AllTypes.class));
assertTrue(realmClasses.contains(CatOwner.class));
assertFalse(realmClasses.contains(Cat.class));
// Tests returned Set is unmodifiable.
try {
realmClasses.add(AllTypes.class);
fail();
} catch (UnsupportedOperationException ignored) {
}
}
@Test
public void rxFactory() {
final RxObservableFactory dummyFactory = new RxObservableFactory() {
@Override
public Observable<Realm> from(Realm realm) {
return null;
}
@Override
public Observable<DynamicRealm> from(DynamicRealm realm) {
return null;
}
@Override
public <E extends RealmModel> Observable<RealmResults<E>> from(Realm realm, RealmResults<E> results) {
return null;
}
@Override
public Observable<RealmResults<DynamicRealmObject>> from(DynamicRealm realm, RealmResults<DynamicRealmObject> results) {
return null;
}
@Override
public <E extends RealmModel> Observable<RealmList<E>> from(Realm realm, RealmList<E> list) {
return null;
}
@Override
public Observable<RealmList<DynamicRealmObject>> from(DynamicRealm realm, RealmList<DynamicRealmObject> list) {
return null;
}
@Override
public <E extends RealmModel> Observable<E> from(Realm realm, E object) {
return null;
}
@Override
public Observable<DynamicRealmObject> from(DynamicRealm realm, DynamicRealmObject object) {
return null;
}
@Override
public <E extends RealmModel> Observable<RealmQuery<E>> from(Realm realm, RealmQuery<E> query) {
return null;
}
@Override
public Observable<RealmQuery<DynamicRealmObject>> from(DynamicRealm realm, RealmQuery<DynamicRealmObject> query) {
return null;
}
};
RealmConfiguration configuration1 = configFactory.createConfigurationBuilder()
.rxFactory(dummyFactory)
.build();
assertTrue(configuration1.getRxFactory() == dummyFactory);
RealmConfiguration configuration2 = configFactory.createConfigurationBuilder()
.build();
assertNotNull(configuration2.getRxFactory());
assertFalse(configuration2.getRxFactory() == dummyFactory);
}
@Test
public void initialDataTransactionEqual() {
final Realm.Transaction transaction = new Realm.Transaction() {
@Override
public void execute(final Realm realm) {
}
};
RealmConfiguration configuration = configFactory.createConfigurationBuilder()
.initialData(transaction)
.build();
assertEquals(transaction, configuration.getInitialDataTransaction());
}
@Test
public void initialDataTransactionNull() {
assertNull(defaultConfig.getInitialDataTransaction());
realm = Realm.getInstance(defaultConfig);
assertTrue(realm.isEmpty());
}
@Test
public void initialDataTransactionNotNull() {
// Removes default instance.
Realm.deleteRealm(defaultConfig);
RealmConfiguration configuration = configFactory.createConfigurationBuilder()
.initialData(new Realm.Transaction() {
@Override
public void execute(final Realm realm) {
realm.createObject(AllTypes.class);
realm.createObject(Owner.class).setCat(realm.createObject(Cat.class));
}
}).build();
realm = Realm.getInstance(configuration);
// First time check for initial data.
assertEquals(1, realm.where(AllTypes.class).count());
assertEquals(1, realm.where(Owner.class).count());
assertEquals(1, realm.where(Cat.class).count());
realm.beginTransaction();
realm.delete(AllTypes.class);
realm.commitTransaction();
assertEquals(0, realm.where(AllTypes.class).count());
realm.close();
realm = Realm.getInstance(configuration);
// Checks if there is still the same data.
assertEquals(0, realm.where(AllTypes.class).count());
assertEquals(1, realm.where(Owner.class).count());
assertEquals(1, realm.where(Cat.class).count());
}
@Test
public void initialDataTransactionExecutionCount() {
// Removes default instance.
Realm.deleteRealm(defaultConfig);
Realm.Transaction transaction = mock(Realm.Transaction.class);
RealmConfiguration configuration = configFactory.createConfigurationBuilder()
.initialData(transaction)
.build();
realm = Realm.getInstance(configuration);
realm.close();
verify(transaction, times(1)).execute(realm);
realm = Realm.getInstance(configuration);
realm.close();
verify(transaction, never()).execute(realm);
}
@Test
public void initialDataTransactionAssetFile() throws IOException {
// Removes default instance.
Realm.deleteRealm(defaultConfig);
Context context = InstrumentationRegistry.getInstrumentation().getContext();
configFactory.copyRealmFromAssets(context, "asset_file.realm", Realm.DEFAULT_REALM_NAME);
assertTrue(new File(configFactory.getRoot(), Realm.DEFAULT_REALM_NAME).exists());
Realm.Transaction transaction = mock(Realm.Transaction.class);
RealmConfiguration configuration = configFactory.createConfigurationBuilder()
.modules(new AssetFileModule())
.initialData(transaction)
.build();
realm = Realm.getInstance(configuration);
realm.close();
verify(transaction, never()).execute(realm);
}
@Test
public void assetFileNullAndEmptyFileName() {
try {
new RealmConfiguration.Builder(context).assetFile(null).build();
fail();
} catch (IllegalArgumentException ignored) {
}
try {
new RealmConfiguration.Builder(context).assetFile("").build();
fail();
} catch (IllegalArgumentException ignored) {
}
}
@Test
public void assetFileWithInMemoryConfig() {
// Ensures that there is no data.
Realm.deleteRealm(new RealmConfiguration.Builder(context).build());
try {
new RealmConfiguration.Builder(context).assetFile("asset_file.realm").inMemory().build();
fail();
} catch (RealmException ignored) {
}
}
@Test
public void assetFileFakeFile() {
// Ensures that there is no data.
Realm.deleteRealm(new RealmConfiguration.Builder(context).build());
RealmConfiguration configuration = new RealmConfiguration.Builder(context).assetFile("no_file").build();
try {
Realm.getInstance(configuration);
fail();
} catch (RealmFileException expected) {
assertEquals(expected.getKind(), RealmFileException.Kind.ACCESS_ERROR);
}
}
@Test
public void assetFileValidFile() throws IOException {
// Ensures that there is no data.
Realm.deleteRealm(new RealmConfiguration.Builder(context).build());
RealmConfiguration configuration = new RealmConfiguration
.Builder(context)
.modules(new AssetFileModule())
.assetFile("asset_file.realm")
.build();
Realm.deleteRealm(configuration);
File realmFile = new File(configuration.getPath());
assertFalse(realmFile.exists());
realm = Realm.getInstance(configuration);
assertTrue(realmFile.exists());
// Asset file has 10 Owners and 10 Cats, checks if data is present.
assertEquals(10, realm.where(Owner.class).count());
assertEquals(10, realm.where(Cat.class).count());
realm.close();
// Copies original file to another location.
configFactory.copyRealmFromAssets(context, "asset_file.realm", "asset_file_copy.realm");
File copyFromAsset = new File(configFactory.getRoot(), "asset_file_copy.realm");
assertTrue(copyFromAsset.exists());
Realm.deleteRealm(configuration);
assertFalse(realmFile.exists());
}
@Test
public void assetFile_failsWhenDeleteRealmIfMigrationNeededConfigured() {
Context context = InstrumentationRegistry.getInstrumentation().getContext();
// Has a builder instance to isolate codepath.
RealmConfiguration.Builder builder = new RealmConfiguration.Builder(context);
try {
builder
.deleteRealmIfMigrationNeeded()
.assetFile("asset_file.realm");
fail();
} catch (IllegalStateException expected) {
assertEquals("Realm cannot use an asset file when previously configured to clear its schema in migration by calling deleteRealmIfMigrationNeeded().",
expected.getMessage());
}
}
private static class MigrationWithNoEquals implements RealmMigration {
@Override
public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {
// Does nothing.
}
}
@Test
public void detectMissingEqualsInCustomMigration() {
RealmConfiguration config1 = configFactory.createConfigurationBuilder().migration(new MigrationWithNoEquals()).build();
RealmConfiguration config2 = configFactory.createConfigurationBuilder().migration(new MigrationWithNoEquals()).build();
Realm realm = Realm.getInstance(config1);
try {
Realm.getInstance(config2);
fail();
} catch (IllegalArgumentException e) {
assertTrue(e.getMessage().contains("The most likely cause is that equals() and hashCode() are not overridden"));
} finally {
realm.close();
}
}
@Test
public void readOnly_initialTransaction_throws() {
// Check assetFile(), then initialTransaction();
RealmConfiguration.Builder config = new RealmConfiguration.Builder()
.assetFile("foo")
.readOnly()
.initialData(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
// Do nothing
}
});
try {
config.build();
fail();
} catch (IllegalStateException ignored) {
}
}
@Test
public void readOnly_deleteRealmIfMigrationRequired_throws() {
try {
// This test doesn't actually fail on 'deleteRealmIfMigrationNeeded' + 'readOnly' but on
// 'assetFile' + 'deleteRealmIfMigrationNeed()'. This test is primarely here to prevent this
// case from accidentally parsing in the future.
new RealmConfiguration.Builder()
.assetFile("foo")
.readOnly()
.deleteRealmIfMigrationNeeded()
.build();
fail();
} catch (IllegalStateException ignored) {
}
}
}