Merge pull request #1314 from realm/tg/listener-test

Fix race conditions in testAddListener
This commit is contained in:
Thomas Goyne 2017-09-19 16:32:33 -07:00 committed by GitHub
commit 936dc15c2a
3 changed files with 60 additions and 33 deletions

View File

@ -54,13 +54,25 @@ function wait(t) {
return new Promise(resolve => setTimeout(resolve, t)); return new Promise(resolve => setTimeout(resolve, t));
} }
function repeatUntil(fn, predicate) {
let retries = 0
function check() {
if (retries > 3) {
return Promise.reject(new Error("operation timed out"));
}
++retries;
return fn().then(x => predicate(x) ? x : wait(100).then(check));
}
return check;
}
module.exports = { module.exports = {
testApplyAndGetGrantedPermissions() { testApplyAndGetGrantedPermissions() {
return createUsersWithTestRealms(1) return createUsersWithTestRealms(1)
.then(([user]) => { .then(([user]) => {
return user.applyPermissions({ userId: '*' }, `/${user.identity}/test`, 'read') return user.applyPermissions({ userId: '*' }, `/${user.identity}/test`, 'read')
.then(wait(100)) .then(repeatUntil(() => user.getGrantedPermissions('any'),
.then(() => user.getGrantedPermissions('any')) permissions => permissions.length > 1))
.then(permissions => { .then(permissions => {
TestCase.assertEqual(permissions[1].path, `/${user.identity}/test`); TestCase.assertEqual(permissions[1].path, `/${user.identity}/test`);
TestCase.assertEqual(permissions[1].mayRead, true); TestCase.assertEqual(permissions[1].mayRead, true);
@ -77,13 +89,15 @@ module.exports = {
.then(token => user2.acceptPermissionOffer(token)) .then(token => user2.acceptPermissionOffer(token))
.then(realmUrl => { .then(realmUrl => {
TestCase.assertEqual(realmUrl, `/${user1.identity}/test`); TestCase.assertEqual(realmUrl, `/${user1.identity}/test`);
return user2.getGrantedPermissions('any') return realmUrl;
.then(permissions => { })
TestCase.assertEqual(permissions[1].path, `/${user1.identity}/test`); .then(repeatUntil(() => user2.getGrantedPermissions('any'),
TestCase.assertEqual(permissions[1].mayRead, true); permissions => permissions.length > 1))
TestCase.assertEqual(permissions[1].mayWrite, false); .then(permissions => {
TestCase.assertEqual(permissions[1].mayManage, false); TestCase.assertEqual(permissions[1].path, `/${user1.identity}/test`);
}); TestCase.assertEqual(permissions[1].mayRead, true);
TestCase.assertEqual(permissions[1].mayWrite, false);
TestCase.assertEqual(permissions[1].mayManage, false);
}); });
}); });
}, },

View File

@ -421,29 +421,40 @@ module.exports = {
}, },
testAddListener: function() { testAddListener: function() {
return new Promise((resolve, _reject) => { if (typeof navigator !== 'undefined' && /Chrome/.test(navigator.userAgent)) { // eslint-disable-line no-undef
var realm = new Realm({ schema: [schemas.TestObject] }); // FIXME: async callbacks do not work correctly in Chrome debugging mode
return;
}
realm.write(() => { const realm = new Realm({ schema: [schemas.TestObject] });
realm.create('TestObject', { doubleCol: 1 }); realm.write(() => {
realm.create('TestObject', { doubleCol: 2 }); realm.create('TestObject', { doubleCol: 1 });
realm.create('TestObject', { doubleCol: 3 }); realm.create('TestObject', { doubleCol: 2 });
}); realm.create('TestObject', { doubleCol: 3 });
});
let resolve, first = true;
return new Promise((r, _reject) => {
resolve = r;
realm.objects('TestObject').addListener((testObjects, changes) => { realm.objects('TestObject').addListener((testObjects, changes) => {
// TODO: First notification is empty, so perform these if (first) {
// assertions on the second call. However, there is a race condition TestCase.assertEqual(testObjects.length, 3);
// in React Native, so find a way to do this in a robust way. TestCase.assertEqual(changes.insertions.length, 0);
//TestCase.assertEqual(testObjects.length, 4); }
//TestCase.assertEqual(changes.insertions.length, 1); else {
TestCase.assertEqual(testObjects.length, 4);
TestCase.assertEqual(changes.insertions.length, 1);
}
first = false;
resolve(); resolve();
}); });
}).then(() => {
realm.write(() => { return new Promise((r, _reject) => {
realm.create('TestObject', { doubleCol: 1 }); realm.write(() => {
realm.create('TestObject', { doubleCol: 1 });
});
resolve = r;
}); });
}) });
} }
}; };

View File

@ -168,6 +168,7 @@ extern NSMutableArray *RCTGetModuleClasses(void);
+ (void)waitForCondition:(BOOL *)condition description:(NSString *)description { + (void)waitForCondition:(BOOL *)condition description:(NSString *)description {
NSRunLoop *runLoop = [NSRunLoop currentRunLoop]; NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
NSDate *timeout = [NSDate dateWithTimeIntervalSinceNow:30.0]; NSDate *timeout = [NSDate dateWithTimeIntervalSinceNow:30.0];
RCTBridge *bridge = [self currentBridge];
while (!*condition) { while (!*condition) {
if ([timeout timeIntervalSinceNow] < 0) { if ([timeout timeIntervalSinceNow] < 0) {
@ -180,6 +181,7 @@ extern NSMutableArray *RCTGetModuleClasses(void);
[runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; [runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
[runLoop runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; [runLoop runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
[NSThread sleepForTimeInterval:0.01]; // Bad things may happen without some sleep. [NSThread sleepForTimeInterval:0.01]; // Bad things may happen without some sleep.
[bridge.eventDispatcher sendAppEventWithName:@"realm-dummy" body:nil]; // Ensure RN has an event loop running
} }
} }
} }