Skip to content

Commit

Permalink
Merge 0e736d9 into d93dd63
Browse files Browse the repository at this point in the history
  • Loading branch information
desistefanova committed Feb 17, 2022
2 parents d93dd63 + 0e736d9 commit 461f29e
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 6 deletions.
20 changes: 16 additions & 4 deletions lib/src/configuration.dart
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,14 @@ class Configuration {
RealmSchema get schema => _schema;

/// Creates a [Configuration] with schema objects for opening a [Realm].
Configuration(List<SchemaObject> schemaObjects)
/// Read-only configuration could be used for opening [Realm] only for reading data in case its file is locked.
/// Realm file must exist before to reopen [Realm] in read-only mode.
Configuration(List<SchemaObject> schemaObjects, {bool readOnly = false})
: _schema = RealmSchema(schemaObjects),
_handle = realmCore.createConfig() {
schemaVersion = 0;
path = defaultPath;
if (readOnly) isReadOnly = readOnly;
realmCore.setSchema(this);
}

Expand All @@ -53,7 +56,7 @@ class Configuration {
}

/// The platform dependent path to the default realm file - `default.realm`.
///
///
/// If set it should contain the name of the realm file. Ex. /mypath/myrealm.realm
static String get defaultPath => _defaultPath ??= _initDefaultPath();
static set defaultPath(String value) => _defaultPath = value;
Expand Down Expand Up @@ -83,10 +86,19 @@ class Configuration {
/// If omitted the [defaultPath] for the platform will be used.
String get path => realmCore.getConfigPath(this);
set path(String value) => realmCore.setConfigPath(this, value);

/// Gets or sets a value indicating whether a [Realm] is opened as readonly. This allows opening it
/// from locked locations such as resources, bundled with an application.
///
/// Realm can not be opened in read-only mode if Realm files do not exist.
/// Opening Realm in read-only mode can be done after reopening existing Realm with read-only configuration.
/// First opening of Realm if configuration is read-only will throw an exception.
bool get isReadOnly => realmCore.getReadOnlyMode(this);
set isReadOnly(bool value) => realmCore.setReadOnlyMode(this, value);
}

/// A collection of properties describing the underlying schema of a [RealmObject].
///
///
/// {@category Configuration}
class SchemaObject {
/// Schema object type.
Expand All @@ -103,7 +115,7 @@ class SchemaObject {
}

/// Describes the complete set of classes which may be stored in a `Realm`
///
///
/// {@category Configuration}
class RealmSchema extends Iterable<SchemaObject> {
///@nodoc
Expand Down
12 changes: 11 additions & 1 deletion lib/src/native/realm_core.dart
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,16 @@ class _RealmCore {
_realmLib.realm_config_set_schema_version(config.handle._pointer, version);
}

bool getReadOnlyMode(Configuration config) {
int mode = _realmLib.realm_config_get_schema_mode(config.handle._pointer);
return mode == realm_schema_mode.RLM_SCHEMA_MODE_READ_ONLY;
}

void setReadOnlyMode(Configuration config, bool value) {
int mode = value ? realm_schema_mode.RLM_SCHEMA_MODE_READ_ONLY : realm_schema_mode.RLM_SCHEMA_MODE_AUTOMATIC;
_realmLib.realm_config_set_schema_mode(config.handle._pointer, mode);
}

ConfigHandle createConfig() {
final configPtr = _realmLib.realm_config_new();
return ConfigHandle._(configPtr);
Expand Down Expand Up @@ -461,7 +471,7 @@ class _RealmCore {
return _realmLib.realm_object_is_valid(object.handle._pointer);
}

bool listIsValid(RealmList list) {
bool listIsValid(RealmList list) {
return _realmLib.realm_list_is_valid(list.handle._pointer);
}
}
Expand Down
107 changes: 106 additions & 1 deletion test/realm_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,112 @@ Future<void> main([List<String>? args]) async {
config.schemaVersion = 3;
expect(config.schemaVersion, equals(3));
});

test('Configuration isReadOnly property - realm files must exist', () {
Configuration config = Configuration([Car.schema]);
config.isReadOnly = true;
//You cannot open Realm in read-only mode if Realm files do not exist.
//Files are created the first time Realm is opened.
//Opening Realm in read-only mode can be done after reopening existing Realm with read-only configuration.
//First opening of Realm if configuration is read-only will throw an exception.
expect(() => Realm(config), throws<RealmException>("Message: No such table exists"));
});

test('Configuration readOnly argument - realm files must exist', () {
Configuration config = Configuration([Car.schema], readOnly: true);
expect(() => Realm(config), throws<RealmException>("Message: No such table exists"));
});

test('Configuration read-only - open existing realm with read-only config', () {
//Create realm and its files
Configuration config = Configuration([Car.schema]);
var realm = Realm(config);
realm.close();

//Reconfigure existing realm for read-only mode.
config = Configuration([Car.schema], readOnly: true);
realm = Realm(config);
realm.close();
});

test('Configuration read-only - reading is possible', () {
Configuration config = Configuration([Car.schema]);
var realm = Realm(config);
realm.write(() => realm.add(Car("Mustang")));
realm.close();

//Reconfigure existing realm for read-only mode.
config.isReadOnly = true;
realm = Realm(config);
var cars = realm.all<Car>();
realm.close();
});

test('Configuration read-only - writing on read-only Realms throws', () {
Configuration config = Configuration([Car.schema]);
var realm = Realm(config);
realm.close();

//Reconfigure existing realm for read-only mode.
config = Configuration([Car.schema], readOnly: true);
realm = Realm(config);
expect(() => realm.write(() => realm.add(Car("Mustang"))), throws<RealmException>("Can't perform transactions on read-only Realms."));
realm.close();
});

test('Configuration read-only - editing realm objects throws', () {
Configuration config = Configuration([Car.schema]);
var realm = Realm(config);
var car = Car("Mustang");
realm.write(() => realm.add(car));
realm.close();

config.isReadOnly = true;
realm = Realm(config);
expect(() => realm.write(() => car.make = "Opel"), throws<RealmException>("Can't perform transactions on read-only Realms."));
realm.close();
});

test('Configuration read-only - deleting realm object throws', () {
Configuration config = Configuration([Car.schema]);
var realm = Realm(config);
var car = Car("Mustang");
realm.write(() => realm.add(car));
realm.close();

config = Configuration([Car.schema], readOnly: true);
realm = Realm(config);
expect(() => realm.write(() => realm.delete(car)), throws<RealmException>("Can't perform transactions on read-only Realms."));
realm.close();
});

test('Configuration read-only - deleting realm results throws', () {
Configuration config = Configuration([Car.schema]);
var realm = Realm(config);
realm.write(() => realm.addAll([Car("Mustang"), Car("Opel")]));
realm.close();

config = Configuration([Car.schema], readOnly: true);
realm = Realm(config);
var cars = realm.all<Car>();
expect(() => realm.write(() => realm.deleteMany(cars)), throws<RealmException>("Can't perform transactions on read-only Realms."));
realm.close();
});

test('Configuration read-only - changing realm lists throws', () {
Configuration config = Configuration([Person.schema, Team.schema]);
var realm = Realm(config);
realm.write(() => realm.add(Team("Boston")..players.addAll([Person("N.M"), Person("K.L")])));
realm.close();

config = Configuration([Person.schema, Team.schema], readOnly: true);
realm = Realm(config);
var team = realm.find<Team>("Boston");
expect(() => realm.write(() => team!.players.clear()), throws<RealmException>("Can't perform transactions on read-only Realms."));
expect(() => realm.write(() => team!.players.add(Person("O.P"))), throws<RealmException>("Can't perform transactions on read-only Realms."));
expect(() => realm.write(() => realm.deleteMany(team!.players)), throws<RealmException>("Can't perform transactions on read-only Realms."));
realm.close();
});
});

group('RealmClass tests:', () {
Expand Down Expand Up @@ -1496,7 +1602,6 @@ Future<void> main([List<String>? args]) async {
realm.close();
});


test('Realm adding objects graph', () {
var studentMichele = Student(1)
..name = "Michele Ernesto"
Expand Down

0 comments on commit 461f29e

Please sign in to comment.