From 99c59541e040fd8a5dcfc0b0e2e21d433dbda966 Mon Sep 17 00:00:00 2001 From: Zachary Boyd Date: Tue, 11 Sep 2018 01:06:53 -0400 Subject: [PATCH] Adds tests for the group feature. Isolates individual tests --- src/TorPool.js | 23 +++ test/TorPool.js | 352 +++++++++++++++++++++++++++++++++++++++------ test/TorProcess.js | 123 +++++++++++++++- test/constants.js | 2 +- 4 files changed, 450 insertions(+), 50 deletions(-) diff --git a/src/TorPool.js b/src/TorPool.js index 78d81cf..88286ba 100644 --- a/src/TorPool.js +++ b/src/TorPool.js @@ -48,6 +48,17 @@ class TorPool extends EventEmitter { get group_names() { return new Set(_.uniq(_.flatten(this.instances.map((instance) => instance.instance_group).filter(Boolean))).sort()); } + + instances_by_group(group_name) { + let group = this.groups[group_name]; + let arr = []; + + for (let i = 0; i < group.length; i++) { + arr.push(group[i]); + } + + return arr; + } add_instance_to_group(group, instance) { instance.definition.Group = _.union(instance.instance_group, [group]); @@ -271,6 +282,10 @@ class TorPool extends EventEmitter { await Promise.all(this.instances.map((instance) => instance.new_identity())); } + async new_identites_by_group(group) { + await Promise.all(this.instances_by_group(group).map((instance) => instance.new_identity())); + } + async new_identity_at(index) { await this.instances[index].new_identity(); } @@ -316,6 +331,14 @@ class TorPool extends EventEmitter { return await instance.set_config(keyword, value); } + async set_config_by_group(group, keyword, value) { + return await Promise.all(this.instances_by_group(group).map((instance) => instance.set_config(keyword, value))); + } + + async signal_by_group(group, signal) { + await Promise.all(this.instances_by_group(group).map((instance) => instance.signal(signal))); + } + async set_config_all(keyword, value) { return await Promise.all(this.instances.map((instance) => instance.set_config(keyword, value))); } diff --git a/test/TorPool.js b/test/TorPool.js index a3f54d0..6474cf0 100644 --- a/test/TorPool.js +++ b/test/TorPool.js @@ -159,24 +159,44 @@ describe('TorPool', function () { }); }); - let torPool; - describe('#next()', function () { - before('create tor pool', () => { torPool = torPoolFactory(); }) + describe('#instances_by_group(group)', function () { + let tor_pool; + let instances; + + before('create tor pool', async function () { + tor_pool = torPoolFactory(); + this.timeout(WAIT_FOR_CREATE); + instances = (await tor_pool.add([ { Name: 'instance-1', Group: [ "bar", "foo" ] }, { Name: 'instance-2', Group: ["foo", "bar"] } ])); + }); + + it('should return both instances', function () { + assert.deepEqual(tor_pool.instances_by_group('bar'), instances); + }); + + after('shutdown tor pool', async function () { await tor_pool.exit(); }); + }); + + describe('#next()', function () { + let torPool; + before('create tor pool', async function () { + torPool = torPoolFactory(); - before('create tor instances', async function () { this.timeout(WAIT_FOR_CREATE * 3); await torPool.add([ { Name: 'instance-1', - Weight: 50 + Weight: 50, + Group: 'foo' }, { Name: 'instance-2', - Weight: 25 + Weight: 25, + Group: 'bar' }, { Name: 'instance-3', - Weight: 2 + Weight: 2, + Group: 'bar' } ]); }); @@ -186,58 +206,177 @@ describe('TorPool', function () { let t2 = torPool.next().instance_name; assert.notEqual(t1, t2); }); + + after('shutdown tor pool', async function () { await torPool.exit(); }); }); describe('#instance_by_name(instance_name)', function () { + let torPool; + before('create tor pool', async function () { + torPool = torPoolFactory(); + + this.timeout(WAIT_FOR_CREATE); + await torPool.add([ + { + Name: 'instance-1' + } + ]); + }); + it('should retrieve instance by name', function () { assert.ok(torPool.instance_by_name('instance-1')); }); + + after('shutdown tor pool', async function () { await torPool.exit(); }); }); describe('#remove_by_name(instance_name)', function () { - this.timeout(5000); - it('should remove instance by name', async function () { - await torPool.remove_by_name('instance-3'); + let torPool; + before('create tor pool', async function () { + torPool = torPoolFactory(); + + this.timeout(WAIT_FOR_CREATE); + await torPool.add([ + { + Name: 'instance-3' + } + ]); }); + + it('should remove instance by name', async function () { + this.timeout(5000); + + await torPool.remove_by_name('instance-3'); + + assert.notIncludeDeepOrderedMembers(torPool.instance_names, [ "instance-3" ]); + }); + + after('shutdown tor pool', async function () { await torPool.exit(); }); }); describe('#instance_at(index)', function () { - this.timeout(5000); + let torPool; + before('create tor pool', async function () { + torPool = torPoolFactory(); + + this.timeout(WAIT_FOR_CREATE); + await torPool.create(1); + + }); + it('should retrieve an instance by id', function () { + this.timeout(5000); assert.ok(torPool.instance_at(0)); }); + + after('shutdown tor pool', async function () { await torPool.exit(); }); }); describe('#remove_at(index)', function () { - this.timeout(5000); - it('should remove an instance by id', async function () { - await torPool.remove_at(1); + let torPool; + before('create tor pool', async function () { + torPool = torPoolFactory(); + + this.timeout(WAIT_FOR_CREATE ); + await torPool.create(1); + }); + + it('should remove an instance by id', async function () { + this.timeout(5000); + await torPool.remove_at(0); + + assert.notOk(torPool.instances[0]); + }); + + after('shutdown tor pool', async function () { await torPool.exit(); }); }); + describe('#new_identites()', function () { - this.timeout(5000); + let torPool; + before('create tor pool', async function () { + torPool = torPoolFactory(); + + this.timeout(WAIT_FOR_CREATE * 2); + await torPool.create(2); + + }); + it('should signal to retrieve a new identity to all instances', async function () { + this.timeout(5000); await torPool.new_identites(); }); + + after('shutdown tor pool', async function () { await torPool.exit(); }); + }); + + describe('#new_identites_by_group(group)', function () { + let torPool; + before('create tor pool', async function () { + torPool = torPoolFactory(); + + this.timeout(WAIT_FOR_CREATE * 3); + await torPool.add([ + { Name: 'instance-1', Group: 'bar' }, + { Name: 'instance-2', Group: 'foo' } + ]); + + }); + + it('should signal to retrieve a new identity to all instances', async function () { + this.timeout(5000); + await torPool.new_identites_by_group('bar'); + }); + + after('shutdown tor pool', async function () { await torPool.exit(); }); }); describe('#new_identity_at(index)', function () { - this.timeout(5000); + let torPool; + before('create tor pool', async function () { + torPool = torPoolFactory(); + + this.timeout(WAIT_FOR_CREATE); + await torPool.create(1); + + }); + it('should signal to retrieve a new identity identified by index', async function () { + this.timeout(5000); await torPool.new_identity_at(0); }); + + after('shutdown tor pool', async function () { await torPool.exit(); }); }); describe('#new_identity_by_name(instance_name)', function () { - this.timeout(5000); + let torPool; + before('create tor pool', async function () { + torPool = torPoolFactory(); + + this.timeout(WAIT_FOR_CREATE); + await torPool.add({ Name: 'instance-1' }); + }); + it('should signal to retrieve a new identity identified by name', async function () { + this.timeout(5000); await torPool.new_identity_by_name('instance-1'); }); + + after('shutdown tor pool', async function () { await torPool.exit(); }); }); describe('#set_config_all(keyword, value)', function () { + let torPool; + before('create tor pool', async function () { + torPool = torPoolFactory(); + + this.timeout(WAIT_FOR_CREATE * 2); + await torPool.create(2); + }); + it('should set configuration on all active instances', async function () { this.timeout(5000); await torPool.set_config_all('TestSocks', 1); @@ -251,65 +390,190 @@ describe('TorPool', function () { assert.isTrue( values.every((value) => value === "1") ); }); - after('unset config options', async function () { - await torPool.set_config_all('TestSocks', 0); + after('shutdown tor pool', async function () { await torPool.exit(); }); + }); + + describe('#set_config_by_group(group, keyword, value)', function () { + let torPool; + before('create tor pool', async function () { + torPool = torPoolFactory(); + + this.timeout(WAIT_FOR_CREATE); + await torPool.add([ { Name: 'instance-1', Group: 'foo' }, { Name: 'instance-2', Group: 'bar' } ]); + }); + + it('should set configuration on all active instances', async function () { + this.timeout(5000); + await torPool.set_config_by_group('bar', 'TestSocks', 1); + }); + + it('all instances should contain the same changed configuration', async function () { + this.timeout(5000); + + let values_from_bar = await Promise.all(torPool.instances_by_group('bar').map((instance) => instance.get_config('TestSocks'))); + values_from_bar = _.flatten(values_from_bar); + assert.isTrue( values_from_bar.every((value) => value === "1") ); + + let values_from_foo = await Promise.all(torPool.instances_by_group('foo').map((instance) => instance.get_config('TestSocks'))); + values_from_foo = _.flatten(values_from_foo); + assert.isTrue( values_from_foo.every((value) => value !== "1") ); + }); + + after('shutdown tor pool', async function () { await torPool.exit(); }); }); describe('#set_config_by_name(name, keyword, value)', function () { - this.timeout(5000); + let torPool; + before('create tor pool', async function () { + torPool = torPoolFactory(); + + this.timeout(WAIT_FOR_CREATE); + await torPool.add({ Name: 'instance-1' }); + + }); + it('should set a configuration property of an instance identified by name', async function () { + this.timeout(5000); await torPool.set_config_by_name('instance-1', 'ProtocolWarnings', 1); }); + + it('should have the set value', async function () { + this.timeout(5000); + let value = _.flatten(await torPool.get_config_by_name('instance-1', 'ProtocolWarnings'))[0]; + assert.equal(value, '1'); + }); + + after('shutdown tor pool', async function () { await torPool.exit(); }); }); describe('#get_config_by_name(name, keyword)', function () { - this.timeout(5000); - it('should get retrieve the configuration of an instance identified by name', async function () { - let value = await torPool.get_config_by_name('instance-1', 'ProtocolWarnings'); - assert.equal(value, 1); + let torPool; + before('create tor pool', async function () { + torPool = torPoolFactory(); + + this.timeout(WAIT_FOR_CREATE); + await torPool.add({ Name: 'instance-1', Config: { ProtocolWarnings: 1 } }); }); + + it('should get retrieve the configuration of an instance identified by name', async function () { + this.timeout(5000); + let value = _.flatten(await torPool.get_config_by_name('instance-1', 'ProtocolWarnings'))[0]; + assert.equal(value, '1'); + }); + + after('shutdown tor pool', async function () { await torPool.exit(); }); }); describe('#set_config_at(index, keyword, value)', function () { - this.timeout(5000); - it('should set a configuration property of an instance identified by index', async function () { - await torPool.set_config_at(0, 'ProtocolWarnings', 0); + let torPool; + before('create tor pool', async function () { + torPool = torPoolFactory(); + + this.timeout(WAIT_FOR_CREATE); + await torPool.create(1); }); + + it('should set a configuration property of an instance identified by index', async function () { + this.timeout(5000); + await torPool.set_config_at(0, 'ProtocolWarnings', 1); + }); + + it('should have the set value', async function () { + this.timeout(5000); + let value = _.flatten(await torPool.get_config_at(0, 'ProtocolWarnings'))[0]; + assert.equal(value, '1'); + }); + + after('shutdown tor pool', async function () { await torPool.exit(); }); }); describe('#get_config_at(index, keyword)', function () { - this.timeout(5000); - it('should get retrieve the configuration of an instance identified by name', async function () { - let value = await torPool.get_config_at(0, 'ProtocolWarnings'); + let torPool; + before('create tor pool', async function () { + torPool = torPoolFactory(); - assert.equal(value, 0); + this.timeout(WAIT_FOR_CREATE); + await torPool.add({ Config: { ProtocolWarnings: 1 } }); }); + + it('should get retrieve the configuration of an instance identified by name', async function () { + this.timeout(5000); + let value = _.flatten(await torPool.get_config_at(0, 'ProtocolWarnings'))[0]; + + assert.equal(value, '1'); + }); + + after('shutdown tor pool', async function () { await torPool.exit(); }); }); describe('#signal_all(signal)', function () { - this.timeout(5000); + let torPool; + before('create tor pool', async function () { + torPool = torPoolFactory(); + + this.timeout(WAIT_FOR_CREATE); + await torPool.create(1); + + }); + it('should send a signal to all instances', async function () { + this.timeout(5000); await torPool.signal_all('DEBUG'); }); + + after('shutdown tor pool', async function () { await torPool.exit(); }); }); describe('#signal_by_name(name, signal)', async function () { - this.timeout(5000); + let torPool; + before('create tor pool', async function () { + torPool = torPoolFactory(); + + this.timeout(WAIT_FOR_CREATE); + await torPool.create({ Name: 'instance-1' }); + }); + it('should send a signal to an instance identified by name', async function () { + this.timeout(5000); await torPool.signal_by_name('instance-1', 'DEBUG'); }); + + after('shutdown tor pool', async function () { await torPool.exit(); }); + }); + + describe('#signal_by_group(group, name, signal)', async function () { + let torPool; + before('create tor pool', async function () { + torPool = torPoolFactory(); + + this.timeout(WAIT_FOR_CREATE); + await torPool.create(1); + }); + + it('should send a signal to an instance identified by name', async function () { + this.timeout(5000); + await torPool.signal_by_group('foo', 'DEBUG'); + }); + + after('shutdown tor pool', async function () { await torPool.exit(); }); }); describe('#signal_at(index, signal)', function () { - this.timeout(5000); + let torPool; + before('create tor pool', async function () { + torPool = torPoolFactory(); + + this.timeout(WAIT_FOR_CREATE); + await torPool.create(1); + }); + it('should send a signal to an instance identified by index', async function () { + this.timeout(5000); await torPool.signal_at(0, 'DEBUG'); }); - }); - after('shutdown tor pool', async function () { - await torPool.exit(); + after('shutdown tor pool', async function () { await torPool.exit(); }); }); describe('#group_names', function () { @@ -329,7 +593,7 @@ describe('TorPool', function () { after('shutdown tor pool', async function () { await tor_pool.exit(); }); }); - + describe('#add_instance_to_group(group, instance)', function () { let tor_pool; let instance; @@ -337,7 +601,7 @@ describe('TorPool', function () { before('create tor pool', async function () { tor_pool = torPoolFactory(); this.timeout(WAIT_FOR_CREATE); - instance = (await tor_pool.create(1)).shift(); + instance = (await tor_pool.create(1))[0]; }); it('should add the instance to the group successfully', function () { @@ -358,7 +622,7 @@ describe('TorPool', function () { before('create tor pool', async function () { tor_pool = torPoolFactory(); this.timeout(WAIT_FOR_CREATE); - instance = (await tor_pool.add({ Name: 'instance-1' })).shift(); + instance = (await tor_pool.add({ Name: 'instance-1' }))[0]; }); it('should add the instance to the group successfully', function () { @@ -379,7 +643,7 @@ describe('TorPool', function () { before('create tor pool', async function () { tor_pool = torPoolFactory(); this.timeout(WAIT_FOR_CREATE); - instance = (await tor_pool.create(1)).shift(); + instance = (await tor_pool.create(1))[0]; }); it('should add the instance to the group successfully', function () { @@ -400,7 +664,7 @@ describe('TorPool', function () { before('create tor pool', async function () { tor_pool = torPoolFactory(); this.timeout(WAIT_FOR_CREATE); - instance = (await tor_pool.add({ Group: "foo" })).shift(); + instance = (await tor_pool.add({ Group: "foo" }))[0]; }); it('should remove the instance from the group successfully', function () { @@ -421,7 +685,7 @@ describe('TorPool', function () { before('create tor pool', async function () { tor_pool = torPoolFactory(); this.timeout(WAIT_FOR_CREATE); - instance = (await tor_pool.add({ Name: 'instance-1', Group: "foo" })).shift(); + instance = (await tor_pool.add({ Name: 'instance-1', Group: "foo" }))[0]; }); it('should remove the instance from the group successfully', function () { @@ -442,7 +706,7 @@ describe('TorPool', function () { before('create tor pool', async function () { tor_pool = torPoolFactory(); this.timeout(WAIT_FOR_CREATE); - instance = (await tor_pool.add({ Group: "foo" })).shift(); + instance = (await tor_pool.add({ Group: "foo" }))[0]; }); it('should remove the instance from the group successfully', function () { diff --git a/test/TorProcess.js b/test/TorProcess.js index 5a5f0e3..cfa0da5 100644 --- a/test/TorProcess.js +++ b/test/TorProcess.js @@ -1,5 +1,6 @@ const nconf = require('nconf'); const { assert } = require('chai'); +const _ = require('lodash'); const { TorProcess } = require('../'); const { WAIT_FOR_CREATE } = require('./constants'); @@ -9,11 +10,71 @@ require(`${__dirname}/../src/nconf_load_env.js`)(nconf); nconf.defaults(require(`${__dirname}/../src/default_config.js`)); describe('TorProcess', function () { - let tor = new TorProcess(nconf.get('torPath'), { Config: { DataDirectory: nconf.get('parentDataDirectory'), ProtocolWarnings: 0 } }, null); + const tor_factory = (d) => { + let defaults = { Config: { DataDirectory: nconf.get('parentDataDirectory') } }; + d = _.extend(_.cloneDeep(defaults), (d || {})); + return new TorProcess(nconf.get('torPath'), d, null); + } + + describe('#instance_name', function () { + let def = { Name: 'foo' }; + before('create tor process', function () { + tor = tor_factory(def); + }); + + it('should have the same name as the definition', function () { + assert.equal(tor.instance_name, def.Name); + }); + }); + + describe('#instance_group', function () { + let def = { Group: ['foo'] }; + before('create tor process', function () { + tor = tor_factory(def); + }); + + it('should have the same group as the definition', function () { + assert.deepEqual(tor.instance_group, def.Group); + }); + }); + + describe('#definition', function () { + let def = { Group: ['foo'], Config: {} }; + before('create tor process', function () { + tor = tor_factory(def); + }); + + it('should be the same as the definition', function () { + let tor_def = _.cloneDeep(tor.definition); + assert.deepEqual(tor.definition, def); + }); + }); + + describe('#exit()', function () { + let tor + before('create tor process', async function () { + tor = tor_factory(); + this.timeout(WAIT_FOR_CREATE); + await tor.create(); + }); + + it('should exit cleanly', async function () { + await tor.exit(); + }); + + it('the process should be dead', function () { + assert.isTrue(tor.process.killed); + }); + }); + describe('#create()', function () { - this.timeout(WAIT_FOR_CREATE); + let tor + before('create tor process', function () { + tor = tor_factory(); + }); it('should create the child process', async function () { + this.timeout(WAIT_FOR_CREATE); await tor.create(); }); @@ -47,34 +108,86 @@ describe('TorProcess', function () { return done(); tor.once('ready', done); }); + + after('exit tor', async function () { + await tor.exit(); + }); }); describe('#set_config(keyword, value)', function () { + let tor + before('create tor process', function (done) { + tor = tor_factory(); + this.timeout(WAIT_FOR_CREATE); + tor.once('controller_ready', done); + tor.create().catch(done); + }); + it('should set sample configuration option via the control protocol', async function () { await tor.set_config('ProtocolWarnings', 1); }); + + it('should have the value set', async function () { + let value = (await tor.get_config('ProtocolWarnings'))[0]; + assert.equal(value, "1"); + }); + + after('exit tor', async function () { + await tor.exit(); + }); }); describe('#get_config(keyword, value)', function () { + let tor + before('create tor process', function (done) { + tor = tor_factory({ Config: { ProtocolWarnings: 1 } }); + this.timeout(WAIT_FOR_CREATE); + tor.once('controller_ready', done); + tor.create().catch(done); + }); + it('should retrieve sample configuration option via the control protocol', async function () { let value = await tor.get_config('ProtocolWarnings'); assert.equal(value, 1); }); + + after('exit tor', async function () { + await tor.exit(); + }); }); describe('#new_identity()', function () { + before('create tor process', function (done) { + tor = tor_factory(); + this.timeout(WAIT_FOR_CREATE); + tor.once('controller_ready', done); + tor.create().catch(done); + }); + it('should use a new identity', async function () { await tor.new_identity(); }); + + after('exit tor', async function () { + await tor.exit(); + }); }); describe('#signal()', function () { + let tor; + before('create tor process', function (done) { + tor = tor_factory(); + this.timeout(WAIT_FOR_CREATE); + tor.once('controller_ready', done); + tor.create().catch(done); + }); + it('should send a signal via the control protocol', async function () { await tor.signal('DEBUG'); }); - }); - after('shutdown tor', async function () { - await tor.exit(); + after('exit tor', async function () { + await tor.exit(); + }); }); }); \ No newline at end of file diff --git a/test/constants.js b/test/constants.js index a315659..f48edd2 100644 --- a/test/constants.js +++ b/test/constants.js @@ -1,4 +1,4 @@ module.exports = { - WAIT_FOR_CREATE: 120000, + WAIT_FOR_CREATE: 240000, PAGE_LOAD_TIME: 60000 }; \ No newline at end of file