File "readwritelock.js"

Full Path: /srv/www/www.cadoro.it/app/lib/locks/test/readwritelock.js
File size: 3.64 KB
MIME-type: text/plain
Charset: utf-8

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();
	});
});