Skip to content

Commit f2c08cf

Browse files
Merge branch '120-sync-completion-test' into 'main'
Sync tests: verify single completion event is sent See merge request objectbox/objectbox-dart!91
2 parents 59bacad + d7e7e32 commit f2c08cf

File tree

2 files changed

+56
-17
lines changed

2 files changed

+56
-17
lines changed

objectbox_test/test/sync_test.dart

+52-13
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import 'dart:async';
12
import 'dart:io';
23
import 'dart:math';
34
import 'dart:typed_data';
@@ -32,6 +33,10 @@ void main() {
3233
env2.closeAndDelete();
3334
});
3435

36+
waitUntilLoggedIn(SyncClient client) {
37+
expect(waitUntil(() => client.state() == SyncState.loggedIn), isTrue);
38+
}
39+
3540
// lambda to easily create clients in the test below
3641
SyncClient createClient(Store s) =>
3742
Sync.client(s, 'ws://127.0.0.1:$serverPort', SyncCredentials.none());
@@ -40,7 +45,7 @@ void main() {
4045
SyncClient loggedInClient(Store s) {
4146
final client = createClient(s);
4247
client.start();
43-
expect(waitUntil(() => client.state() == SyncState.loggedIn), isTrue);
48+
waitUntilLoggedIn(client);
4449
return client;
4550
}
4651

@@ -215,7 +220,7 @@ void main() {
215220
await server.online();
216221
client.start();
217222

218-
expect(waitUntil(() => client.state() == SyncState.loggedIn), isTrue);
223+
waitUntilLoggedIn(client);
219224
await yieldExecution();
220225
expect(events, equals([SyncConnectionEvent.connected]));
221226
expect(events2, equals([SyncConnectionEvent.connected]));
@@ -237,7 +242,7 @@ void main() {
237242
await server.start(keepDb: true);
238243
await server.online();
239244

240-
expect(waitUntil(() => client.state() == SyncState.loggedIn), isTrue);
245+
waitUntilLoggedIn(client);
241246
await yieldExecution();
242247

243248
expect(
@@ -270,7 +275,7 @@ void main() {
270275

271276
client.setCredentials(SyncCredentials.none());
272277

273-
expect(waitUntil(() => client.state() == SyncState.loggedIn), isTrue);
278+
waitUntilLoggedIn(client);
274279
await yieldExecution();
275280
expect(
276281
events,
@@ -283,21 +288,51 @@ void main() {
283288
test('SyncClient listeners: completion', () async {
284289
await server.online();
285290
final client = loggedInClient(store);
291+
addTearDown(() {
292+
client.close();
293+
});
286294
final box = env.store.box<TestEntitySynced>();
287295
final box2 = env2.store.box<TestEntitySynced>();
288296
expect(box.isEmpty(), isTrue);
289-
int id = box.put(TestEntitySynced(value: 100));
297+
// Do multiple changes to verify only a single completion event is sent
298+
// after all changes are received.
299+
box.put(TestEntitySynced(value: 1));
300+
box.put(TestEntitySynced(value: 100));
290301

291302
// Note: wait for the client to finish sending to the server.
292303
// There's currently no other way to recognize this.
293304
sleep(const Duration(milliseconds: 100));
294-
client.close();
295305

296-
final client2 = loggedInClient(env2.store);
297-
await client2.completionEvents.first.timeout(defaultTimeout);
298-
client2.close();
306+
final client2 = createClient(env2.store);
307+
addTearDown(() {
308+
client2.close();
309+
});
310+
final Completer firstEvent = Completer();
311+
var receivedEvents = 0;
312+
final subscription = client2.completionEvents.listen((event) {
313+
if (!firstEvent.isCompleted) {
314+
firstEvent.complete();
315+
}
316+
receivedEvents++;
317+
});
299318

300-
expect(box2.get(id)!.value, 100);
319+
client2.start();
320+
waitUntilLoggedIn(client2);
321+
322+
// Yield and wait for the first event...
323+
await firstEvent.future.timeout(defaultTimeout);
324+
// ...and some more on any additional events (should be none)
325+
await Future.delayed(Duration(milliseconds: 200));
326+
expect(receivedEvents, 1);
327+
// Note: the ID just happens to be the same as the box was unused
328+
expect(box2.get(2)!.value, 100);
329+
330+
// Do another change
331+
box.put(TestEntitySynced(value: 200));
332+
// Yield and wait for event(s) to come in
333+
await Future.delayed(Duration(milliseconds: 200));
334+
await subscription.cancel();
335+
expect(receivedEvents, 2);
301336
});
302337

303338
test('SyncClient listeners: changes', () async {
@@ -415,9 +450,13 @@ class SyncServer {
415450
await httpClient.get('127.0.0.1', _port!, '');
416451
break;
417452
} on SocketException catch (e) {
418-
// only retry if "connection refused"
419-
if (e.osError!.errorCode != 111) rethrow;
420-
await Future<void>.delayed(const Duration(milliseconds: 1));
453+
// Only retry if "Connection refused" (not using error codes as they
454+
// differ by platform).
455+
if (e.osError!.message.contains('Connection refused')) {
456+
await Future<void>.delayed(const Duration(milliseconds: 1));
457+
} else {
458+
rethrow;
459+
}
421460
}
422461
}
423462
httpClient.close(force: true);

objectbox_test/test/test_env.dart

+4-4
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,10 @@ bool waitUntil(bool Function() predicate, {Duration timeout = defaultTimeout}) {
111111
/// same as package:test unorderedEquals() but statically typed
112112
Matcher sameAsList<T>(List<T> list) => unorderedEquals(list);
113113

114-
// Yield execution to other isolates.
115-
//
116-
// We need to do this to receive an event in the stream before processing
117-
// the remainder of the test case.
114+
/// Yield execution to other isolates.
115+
///
116+
/// Do this to receive an event in the stream before processing
117+
/// the remainder of the test case.
118118
Future<void> yieldExecution() async =>
119119
await Future<void>.delayed(Duration.zero);
120120

0 commit comments

Comments
 (0)