var locks = require('..'); var test = require('tape'); function baseTests(t, rwLock) { t.throws(function () { rwLock.unlock(); }, 'Cannot unlock an unlocked ReadWrite lock'); } function multiRead(t, rwLock) { t.equal(rwLock.isLocked, false, 'Unlocked'); var count = 0; rwLock.readLock(function () { t.equal(rwLock.isLocked, 'R', 'Read-locked'); count += 1; t.equal(count, 1, 'First read lock fired immediately'); rwLock.readLock(function () { t.equal(rwLock.isLocked, 'R', 'Still read-locked'); count += 1; t.equal(count, 2, 'Second read lock fired immediately'); }); }); count = -1; rwLock.unlock(); t.equal(rwLock.isLocked, 'R', 'Still read-locked'); rwLock.unlock(); } function readWriteCombo(t, rwLock) { t.equal(rwLock.isLocked, false, 'Unlocked'); var count = ''; rwLock.readLock(function () { count += 'R'; }); rwLock.writeLock(function () { count += 'W'; rwLock.readLock(function () { count += 'R'; }); }); rwLock.readLock(function () { count += 'R'; }); t.equal(count, 'RR', 'Not yet write-locked'); rwLock.unlock(); rwLock.unlock(); t.equal(rwLock.isLocked, 'W', 'Write-locked'); t.equal(count, 'RRW', 'Write-locked'); rwLock.unlock(); t.equal(count, 'RRWR', 'Read-locked'); rwLock.unlock(); } function manyWriters(t, rwlock) { var count = ''; rwlock.writeLock(function () { count += 'W'; }); rwlock.writeLock(function () { count += 'W'; }); rwlock.writeLock(function () { count += 'W'; }); t.equal(count, 'W'); rwlock.unlock(); t.equal(count, 'WW'); rwlock.unlock(); t.equal(count, 'WWW'); rwlock.unlock(); } function triers(t, rwLock) { var success; success = rwLock.tryWriteLock(); t.equal(success, true, 'Try WriteLock success'); success = rwLock.tryWriteLock(); t.equal(success, false, 'Try WriteLock failure'); success = rwLock.tryReadLock(); t.equal(success, false, 'Try ReadLock failure'); rwLock.unlock(); success = rwLock.tryReadLock(); t.equal(success, true, 'Try ReadLock success'); success = rwLock.tryReadLock(); t.equal(success, true, 'Try ReadLock success'); success = rwLock.tryWriteLock(); t.equal(success, false, 'Try WriteLock failure'); rwLock.unlock(); rwLock.unlock(); } function timed(t, rwLock, cb) { // should fire instantly: rwLock.timedReadLock(10, function () {}); t.equal(rwLock.isLocked, 'R', 'Read-locked'); rwLock.timedWriteLock(1, function (error) { t.ok(error, 'Write-lock attempt timed out'); // we expect an error }); setTimeout(function () { rwLock.unlock(); rwLock.writeLock(function () {}); t.equal(rwLock.isLocked, 'W', 'Write-locked'); rwLock.timedReadLock(1000, function () { t.equal(rwLock.isLocked, 'R', 'Read-locked'); rwLock.timedWriteLock(10, function () { t.equal(rwLock.isLocked, 'W', 'Write-locked'); // write lock that times out: rwLock.timedWriteLock(1, function (error) { t.ok(error, 'Write-lock timed out'); rwLock.unlock(); t.equal(rwLock.isLocked, false, 'Unlocked'); // should fire instantly: rwLock.timedWriteLock(1000, function () {}); t.equal(rwLock.isLocked, 'W', 'Write-locked'); // write lock that times out: rwLock.timedReadLock(1, function (error) { t.ok(error, 'Read-lock timed out'); rwLock.unlock(); cb(); }); }); }); setTimeout(function () { rwLock.unlock(); }, 1); }); setTimeout(function () { rwLock.unlock(); }, 1); }, 10); } test('ReadWriteLock', function (t) { var rwLock = locks.createReadWriteLock(); baseTests(t, rwLock); multiRead(t, rwLock); readWriteCombo(t, rwLock); manyWriters(t, rwLock); triers(t, rwLock); timed(t, rwLock, function () { t.end(); }); });