Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Throws last core error when beginWriteAsync and commitWriteAsync #974

Merged
merged 14 commits into from
Dec 12, 2022
Merged
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
### Breaking Changes
* File format version bumped.
* The layout of the lock-file has changed, the lock file format version is bumped and all participants in a multiprocess scenario needs to be up to date so they expect the same format. This requires an update of Studio. (Core upgrade)
* Writing to a frozen realm throws `RealmException` instead of `RealmError`. ([#974](https://github.com/realm/realm-dart/pull/974))

### Enhancements
* Support setting `maxNumberOfActiveVersions` when creating a `Configuration`. ([#1036](https://github.com/realm/realm-dart/pull/1036))
Expand All @@ -20,6 +21,7 @@
* Removed the ".tmp_compaction_space" file being left over after compacting a Realm on Windows. (Core upgrade).
* Restore fallback to full barrier when F_BARRIERSYNC is not available on Apple platforms. (Core upgrade, since v0.8.0+rc)
* Fixed wrong assertion on query error that could result in a crash. (Core upgrade)
* Writing to a read-only realm throws `RealmException` insted to block the isolate. ([#974](https://github.com/realm/realm-dart/pull/974))
desistefanova marked this conversation as resolved.
Show resolved Hide resolved

### Compatibility
* Realm Studio: 13.0.0 or later.
Expand Down
12 changes: 0 additions & 12 deletions lib/src/realm_class.dart
Original file line number Diff line number Diff line change
Expand Up @@ -321,20 +321,14 @@ class Realm implements Finalizable {

/// Begins a write transaction for this [Realm].
Transaction beginWrite() {
_ensureWritable();

realmCore.beginWrite(this);

return Transaction._(this);
}

/// Asynchronously begins a write transaction for this [Realm]. You can supply a
/// [CancellationToken] to cancel the operation.
Future<Transaction> beginWriteAsync([CancellationToken? cancellationToken]) async {
_ensureWritable();

await realmCore.beginWriteAsync(this, cancellationToken);

return Transaction._(this);
}

Expand Down Expand Up @@ -496,12 +490,6 @@ class Realm implements Finalizable {
}
}

void _ensureWritable() {
blagoev marked this conversation as resolved.
Show resolved Hide resolved
if (isFrozen) {
throw RealmError('Starting a write transaction on a frozen Realm is not allowed.');
}
}

/// Compacts a Realm file. A Realm file usually contains free/unused space.
///
/// This method removes this free space and the file size is thereby reduced.
Expand Down
5 changes: 3 additions & 2 deletions test/configuration_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -174,14 +174,15 @@ Future<void> main([List<String>? args]) async {
expect(cars.length, 1);
});

test('Configuration readOnly - writing on read-only Realms throws', () {
desistefanova marked this conversation as resolved.
Show resolved Hide resolved
test('Configuration readOnly - writing on read-only Realms throws', () async {
Configuration config = Configuration.local([Car.schema]);
var realm = getRealm(config);
realm.close();

config = Configuration.local([Car.schema], isReadOnly: true);
realm = getRealm(config);
expect(() => realm.write(() {}), throws<RealmException>("Can't perform transactions on read-only Realms."));
realm.writesExpectException<RealmException>("Can't perform transactions on read-only Realms.");
await realm.asyncWritesExpectException<RealmException>("Can't perform transactions on read-only Realms.");
});

test('Configuration inMemory - no files after closing realm', () {
Expand Down
44 changes: 9 additions & 35 deletions test/realm_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -268,14 +268,15 @@ Future<void> main([List<String>? args]) async {
expect(realm.write(() => realm.add(carTwo, update: true)), carTwo);
});

test('Realm write after realm is closed', () {
test('Realm write after realm is closed', () async {
var config = Configuration.local([Car.schema]);
var realm = getRealm(config);

final car = Car('Tesla');

realm.close();
expect(() => realm.write(() {}), throws<RealmClosedError>("Cannot access realm that has been closed"));
realm.writesExpectException<RealmClosedError>("Cannot access realm that has been closed");
await realm.asyncWritesExpectException<RealmClosedError>("Cannot access realm that has been closed");
});

test('Realm query', () {
Expand Down Expand Up @@ -576,12 +577,12 @@ Future<void> main([List<String>? args]) async {
expect(returnedCar, car);
});

test('Realm write inside another write throws', () {
test('Realm write inside another write throws', () async {
nirinchev marked this conversation as resolved.
Show resolved Hide resolved
final config = Configuration.local([Car.schema]);
final realm = getRealm(config);
realm.write(() {
realm.write(() async {
nirinchev marked this conversation as resolved.
Show resolved Hide resolved
// Second write inside the first one fails but the error is caught
expect(() => realm.write(() {}), throws<RealmException>('The Realm is already in a write transaction'));
realm.writesExpectException<RealmException>("The Realm is already in a write transaction");
});
});

Expand Down Expand Up @@ -719,36 +720,13 @@ Future<void> main([List<String>? args]) async {
expect(realm.all<Person>().length, 0);
});

test('FrozenRealm cannot write', () {
final config = Configuration.local([Person.schema]);
final realm = getRealm(config);

final frozenRealm = freezeRealm(realm);
expect(() => frozenRealm.write(() {}), throws<RealmError>("Starting a write transaction on a frozen Realm is not allowed."));
});

test('FrozenRealm cannot beginWrite', () {
test('FrozenRealm cannot write', () async {
final config = Configuration.local([Person.schema]);
final realm = getRealm(config);

final frozenRealm = freezeRealm(realm);
expect(() => frozenRealm.beginWrite(), throws<RealmError>("Starting a write transaction on a frozen Realm is not allowed."));
});

test('FrozenRealm cannot writeAsync', () async {
final config = Configuration.local([Person.schema]);
final realm = getRealm(config);

final frozenRealm = freezeRealm(realm);
await expectLater(() => frozenRealm.writeAsync(() {}), throws<RealmError>("Starting a write transaction on a frozen Realm is not allowed."));
});

test('FrozenRealm cannot beginWriteAsync', () async {
final config = Configuration.local([Person.schema]);
final realm = getRealm(config);

final frozenRealm = freezeRealm(realm);
await expectLater(() => frozenRealm.beginWriteAsync(), throws<RealmError>("Starting a write transaction on a frozen Realm is not allowed."));
frozenRealm.writesExpectException<RealmException>("Can't perform transactions on a frozen Realm");
await frozenRealm.asyncWritesExpectException<RealmException>("Can't perform transactions on a frozen Realm");
});

test('realm.freeze when frozen returns the same instance', () {
Expand Down Expand Up @@ -1018,7 +996,6 @@ Future<void> main([List<String>? args]) async {
test('Realm.beginWriteAsync starts write transaction', () async {
final realm = getRealm(Configuration.local([Person.schema]));
final transaction = await realm.beginWriteAsync();

expect(transaction.isOpen, true);
});

Expand All @@ -1027,7 +1004,6 @@ Future<void> main([List<String>? args]) async {
final transaction = await realm.beginWriteAsync();
realm.add(Person('John'));
transaction.commit();

expect(realm.all<Person>().length, 1);
});

Expand All @@ -1036,7 +1012,6 @@ Future<void> main([List<String>? args]) async {
final transaction = await realm.beginWriteAsync();
realm.add(Person('John'));
await transaction.commitAsync();

expect(realm.all<Person>().length, 1);
});

Expand All @@ -1054,7 +1029,6 @@ Future<void> main([List<String>? args]) async {
final transaction = realm.beginWrite();
realm.add(Person('John'));
await transaction.commitAsync();

expect(realm.all<Person>().length, 1);
});

Expand Down
13 changes: 13 additions & 0 deletions test/test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -710,3 +710,16 @@ Future<void> enableAllAutomaticRecovery() async {
await client.setAutomaticRecoveryEnabled(appName, true);
}
}


extension $WriteExtension on Realm {
desistefanova marked this conversation as resolved.
Show resolved Hide resolved
desistefanova marked this conversation as resolved.
Show resolved Hide resolved
void writesExpectException<TException>(String exceptionMessage) {
desistefanova marked this conversation as resolved.
Show resolved Hide resolved
desistefanova marked this conversation as resolved.
Show resolved Hide resolved
expect(() => write(() {}), throws<TException>(exceptionMessage));
expect(() => beginWrite(), throws<TException>(exceptionMessage));
}

Future<void> asyncWritesExpectException<TException>(String exceptionMessage) async {
await expectLater(() => writeAsync(() {}), throws<TException>(exceptionMessage));
await expectLater(() => beginWriteAsync(), throws<TException>(exceptionMessage));
}
}