Adds tests for the group feature.
This commit is contained in:
parent
22908b7bba
commit
f7537bbf8e
|
@ -3,6 +3,7 @@
|
|||
## [4.0.0] - 2018-09-09
|
||||
|
||||
### Added
|
||||
- Instances can now added to one or multiple groups by setting the `Group` field in the instance definition to a single string or array.
|
||||
- You can now proxy through a specific instance using the username field when connecting to a proxy. Setting `--proxyByName` or `-n` to false will disable this feature. For example to connect to an instance named `instance-1` via http use `http://instance-1:@localhost:9080`.
|
||||
- The control server will accept WebSocket connections if the `--websocketControlHost` or `-w` argument is set. If the argument is used without a hostname it will default to 9078 on all interfaces.
|
||||
- All servers (DNS, HTTP, SOCKS and Control) all have a `listen` method which takes a port and optionally, a host returns a Promise that will resolve when the server is listening.
|
||||
|
|
|
@ -19,7 +19,7 @@ class ControlServer {
|
|||
server.expose('createHTTPServer', this.createHTTPServer.bind(this));
|
||||
|
||||
const instance_info = (i) => {
|
||||
return { name: i.instance_name, dns_port: i.dns_port, socks_port: i.socks_port, process_id: i.process.pid, config: i.definition.Config, weight: i.definition.weight };
|
||||
return { group: i.instance_group, name: i.instance_name, dns_port: i.dns_port, socks_port: i.socks_port, process_id: i.process.pid, config: i.definition.Config, weight: i.definition.weight };
|
||||
};
|
||||
|
||||
server.expose('queryInstances', (async () => {
|
||||
|
|
|
@ -46,7 +46,7 @@ class TorPool extends EventEmitter {
|
|||
}
|
||||
|
||||
get group_names() {
|
||||
return _.uniq(_.flatten(this.instances.map((instance) => instance.instance_group).filter(Boolean)));
|
||||
return new Set(_.uniq(_.flatten(this.instances.map((instance) => instance.instance_group).filter(Boolean))).sort());
|
||||
}
|
||||
|
||||
add_instance_to_group(group, instance) {
|
||||
|
@ -117,6 +117,9 @@ class TorPool extends EventEmitter {
|
|||
return (instance_index) => {
|
||||
return this.remove_instance_from_group(group_name, instances[instance_index]);
|
||||
};
|
||||
|
||||
if (prop === 'length')
|
||||
return instances.length;
|
||||
|
||||
return void(0);
|
||||
}
|
||||
|
@ -126,10 +129,12 @@ class TorPool extends EventEmitter {
|
|||
get: (group_names, prop) => {
|
||||
let instances_in_group = [];
|
||||
|
||||
if (group_names.indexOf(prop) !== -1) {
|
||||
if (group_names.has(prop)) {
|
||||
instances_in_group = this.instances.filter((instance) => instance.instance_group.indexOf(prop) !== -1);
|
||||
}
|
||||
|
||||
instances_in_group = _.sortBy(instances_in_group, 'instance_name');
|
||||
|
||||
instances_in_group.group_name = prop;
|
||||
|
||||
return new Proxy(instances_in_group, groupHandler);
|
||||
|
@ -174,10 +179,17 @@ class TorPool extends EventEmitter {
|
|||
return this._instances.slice(0);
|
||||
}
|
||||
|
||||
get instance_names() {
|
||||
return this.instances.map((i) => i.instance_name);
|
||||
}
|
||||
|
||||
async create_instance(instance_definition) {
|
||||
if (!(fs.existsSync(this.data_directory)))
|
||||
await fs.mkdirAsync(this.data_directory);
|
||||
|
||||
if (instance_definition.Name && this.instance_names.indexOf(instance_definition.Name) !== -1)
|
||||
throw new Error(`Instance named ${instance_definition.Name} already exists`);
|
||||
|
||||
this._instances._weighted_list = void(0);
|
||||
instance_definition.Config = _.extend(_.cloneDeep(this.default_tor_config), (instance_definition.Config || {}));
|
||||
let instance_id = nanoid();
|
||||
|
@ -217,7 +229,7 @@ class TorPool extends EventEmitter {
|
|||
}
|
||||
|
||||
instance_by_name(name) {
|
||||
return this._instances.filter((i) => i.definition.Name === name)[0];
|
||||
return this._instances.filter((i) => i.instance_name === name)[0];
|
||||
}
|
||||
|
||||
instance_at(index) {
|
||||
|
|
254
test/TorPool.js
254
test/TorPool.js
|
@ -13,6 +13,32 @@ nconf.defaults(require(`${__dirname}/../src/default_config.js`));
|
|||
describe('TorPool', function () {
|
||||
const torPoolFactory = () => new TorPool(nconf.get('torPath'), {}, nconf.get('parentDataDirectory'), 'round_robin', null);
|
||||
|
||||
describe('#default_tor_config', function () {
|
||||
let tor_pool;
|
||||
let cfg = { "TestSocks": 1, "Log": "notice stdout", "NewCircuitPeriod": "10" };
|
||||
|
||||
before('create tor config based on nconf', function () {
|
||||
nconf.set('torConfig', cfg);
|
||||
tor_pool = new TorPool(nconf.get('torPath'), (() => nconf.get('torConfig')), nconf.get('parentDataDirectory'), 'round_robin', null);
|
||||
});
|
||||
|
||||
it('the tor config should have the same value as set in nconf', function () {
|
||||
assert.deepEqual(nconf.get('torConfig'), tor_pool.default_tor_config);
|
||||
});
|
||||
|
||||
after('shutdown tor pool', async function () { await tor_pool.exit(); });
|
||||
|
||||
before('create tor config based on nconf', function () {
|
||||
tor_pool = new TorPool(nconf.get('torPath'), cfg, nconf.get('parentDataDirectory'), 'round_robin', null);
|
||||
});
|
||||
|
||||
it('the tor config should have the same value as set', function () {
|
||||
assert.deepEqual(cfg, tor_pool.default_tor_config);
|
||||
});
|
||||
|
||||
after('shutdown tor pool', async function () { await tor_pool.exit(); });
|
||||
});
|
||||
|
||||
describe('#create_instance(instance_defintion)', function () {
|
||||
let instance_defintion = {
|
||||
Name: 'instance-1',
|
||||
|
@ -42,8 +68,22 @@ describe('TorPool', function () {
|
|||
assert.equal(value, instance_defintion.Config.ProtocolWarnings);
|
||||
});
|
||||
|
||||
it('should not be able to create an instance with an existing name', async function () {
|
||||
let fn = () => {}
|
||||
|
||||
try {
|
||||
await torPool.create_instance({ Name: 'foo' });
|
||||
await torPool.create_instance({ Name: 'foo' });
|
||||
}
|
||||
catch (error) {
|
||||
fn = () => { throw error };
|
||||
} finally {
|
||||
assert.throws(fn);
|
||||
}
|
||||
});
|
||||
|
||||
after('shutdown tor pool', async function () {
|
||||
torPool.exit();
|
||||
await torPool.exit();
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -271,4 +311,216 @@ describe('TorPool', function () {
|
|||
after('shutdown tor pool', async function () {
|
||||
await torPool.exit();
|
||||
});
|
||||
|
||||
describe('#group_names', function () {
|
||||
let tor_pool;
|
||||
before('create tor pool', async function () {
|
||||
tor_pool = torPoolFactory();
|
||||
this.timeout(WAIT_FOR_CREATE * 2);
|
||||
await tor_pool.add([
|
||||
{ Name: 'instance-1', Group: [ "foo", "bar" ] },
|
||||
{ Name: 'instance-2', Group: "baz" }
|
||||
]);
|
||||
});
|
||||
|
||||
it('the pool should contain three groups, bar, baz and foo', function () {
|
||||
assert.deepEqual(tor_pool.group_names, (new Set([ "bar", "baz", "foo" ])));
|
||||
});
|
||||
|
||||
after('shutdown tor pool', async function () { await tor_pool.exit(); });
|
||||
});
|
||||
|
||||
describe('#add_instance_to_group(group, instance)', function () {
|
||||
let tor_pool;
|
||||
let instance;
|
||||
|
||||
before('create tor pool', async function () {
|
||||
tor_pool = torPoolFactory();
|
||||
this.timeout(WAIT_FOR_CREATE);
|
||||
instance = (await tor_pool.create(1)).shift();
|
||||
});
|
||||
|
||||
it('should add the instance to the group successfully', function () {
|
||||
tor_pool.add_instance_to_group("foo", instance);
|
||||
});
|
||||
|
||||
it('the instance should be added to the group', function () {
|
||||
assert.deepEqual(instance.instance_group, ["foo"]);
|
||||
});
|
||||
|
||||
after('shutdown tor pool', async function () { await tor_pool.exit(); });
|
||||
});
|
||||
|
||||
describe('#add_instance_to_group_by_name(group, instance_name)', function () {
|
||||
let tor_pool;
|
||||
let instance;
|
||||
|
||||
before('create tor pool', async function () {
|
||||
tor_pool = torPoolFactory();
|
||||
this.timeout(WAIT_FOR_CREATE);
|
||||
instance = (await tor_pool.add({ Name: 'instance-1' })).shift();
|
||||
});
|
||||
|
||||
it('should add the instance to the group successfully', function () {
|
||||
tor_pool.add_instance_to_group_by_name("foo", instance.definition.Name);
|
||||
});
|
||||
|
||||
it('the instance should be added to the group', function () {
|
||||
assert.deepEqual(instance.instance_group, ["foo"]);
|
||||
});
|
||||
|
||||
after('shutdown tor pool', async function () { await tor_pool.exit(); });
|
||||
});
|
||||
|
||||
describe('#add_instance_to_group_at(group, instance_index)', function () {
|
||||
let tor_pool;
|
||||
let instance;
|
||||
|
||||
before('create tor pool', async function () {
|
||||
tor_pool = torPoolFactory();
|
||||
this.timeout(WAIT_FOR_CREATE);
|
||||
instance = (await tor_pool.create(1)).shift();
|
||||
});
|
||||
|
||||
it('should add the instance to the group successfully', function () {
|
||||
tor_pool.add_instance_to_group_at("foo", 0);
|
||||
});
|
||||
|
||||
it('the instance should be added to the group', function () {
|
||||
assert.deepEqual(instance.instance_group, ["foo"]);
|
||||
});
|
||||
|
||||
after('shutdown tor pool', async function () { await tor_pool.exit(); });
|
||||
});
|
||||
|
||||
describe('#remove_instance_from_group(group, instance)', function () {
|
||||
let tor_pool;
|
||||
let instance;
|
||||
|
||||
before('create tor pool', async function () {
|
||||
tor_pool = torPoolFactory();
|
||||
this.timeout(WAIT_FOR_CREATE);
|
||||
instance = (await tor_pool.add({ Group: "foo" })).shift();
|
||||
});
|
||||
|
||||
it('should remove the instance from the group successfully', function () {
|
||||
tor_pool.remove_instance_from_group("foo", instance);
|
||||
});
|
||||
|
||||
it('the instance should be no longer be in the group', function () {
|
||||
assert.notIncludeOrderedMembers(instance.instance_group, ["foo"]);
|
||||
});
|
||||
|
||||
after('shutdown tor pool', async function () { await tor_pool.exit(); });
|
||||
});
|
||||
|
||||
describe('#remove_instance_from_group_by_name(group, instance_name)', function () {
|
||||
let tor_pool;
|
||||
let instance;
|
||||
|
||||
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();
|
||||
});
|
||||
|
||||
it('should remove the instance from the group successfully', function () {
|
||||
tor_pool.remove_instance_from_group_by_name("foo", instance.definition.Name);
|
||||
});
|
||||
|
||||
it('the instance should no longer be in the group', function () {
|
||||
assert.notIncludeOrderedMembers(instance.instance_group, ["foo"]);
|
||||
});
|
||||
|
||||
after('shutdown tor pool', async function () { await tor_pool.exit(); });
|
||||
});
|
||||
|
||||
describe('#remove_instance_from_group_at(group, instance_index)', function () {
|
||||
let tor_pool;
|
||||
let instance;
|
||||
|
||||
before('create tor pool', async function () {
|
||||
tor_pool = torPoolFactory();
|
||||
this.timeout(WAIT_FOR_CREATE);
|
||||
instance = (await tor_pool.add({ Group: "foo" })).shift();
|
||||
});
|
||||
|
||||
it('should remove the instance from the group successfully', function () {
|
||||
tor_pool.remove_instance_from_group_at("foo", 0);
|
||||
});
|
||||
|
||||
it('the instance should no longer be in the group', function () {
|
||||
assert.notIncludeOrderedMembers(instance.instance_group, ["foo"]);
|
||||
});
|
||||
|
||||
after('shutdown tor pool', async function () { await tor_pool.exit(); });
|
||||
});
|
||||
|
||||
describe('#groups', function () {
|
||||
let tor_pool;
|
||||
let instances;
|
||||
|
||||
let get_instance_names = (group_name) => {
|
||||
let instances = [];
|
||||
let group = tor_pool.groups[group_name];
|
||||
for (let i = 0; i < group.length; i++)
|
||||
instances.push(group[i]);
|
||||
|
||||
return instances.map((i) => i.instance_name);
|
||||
};
|
||||
|
||||
before('create tor pool', async function () {
|
||||
tor_pool = torPoolFactory();
|
||||
this.timeout(WAIT_FOR_CREATE * 2);
|
||||
instances = (await tor_pool.add([
|
||||
{ Group: "foo", Name: 'instance-1' },
|
||||
{ Group: ["bar", "baz"], Name: 'instance-2' }
|
||||
]));
|
||||
});
|
||||
|
||||
it('should contain three groups, bar, baz and foo', function () {
|
||||
assert.deepEqual(Array.from(tor_pool.group_names), [ "bar", "baz", "foo" ]);
|
||||
});
|
||||
|
||||
it('#[Number] - the 1st element should be "instance-1"', function () {
|
||||
assert.equal(tor_pool.groups["foo"][0], instances[0]);
|
||||
});
|
||||
|
||||
it('#length - group "foo" should contain 1 instance', function () {
|
||||
assert.equal(tor_pool.groups["foo"].length, 1);
|
||||
});
|
||||
|
||||
it('#add - adding "instance-1" to "baz" should result in "baz" having "instance-1" and "instance-2"', function () {
|
||||
tor_pool.groups["baz"].add(instances[0]);
|
||||
|
||||
assert.deepEqual(get_instance_names("baz"), [ "instance-1", "instance-2" ] );
|
||||
});
|
||||
|
||||
it('#remove - removing "instance-1" firom "baz" should result in "baz" having just "instance-2"', function () {
|
||||
tor_pool.groups["baz"].remove(instances[0]);
|
||||
|
||||
assert.deepEqual(get_instance_names("baz"), [ "instance-2" ] );
|
||||
});
|
||||
|
||||
it('#add_by_name - adding "instance-1" to "baz" should result in "baz" having "instance-1" and "instance-2"', function () {
|
||||
tor_pool.groups["baz"].add_by_name('instance-1');
|
||||
|
||||
assert.deepEqual(get_instance_names("baz"), [ "instance-1", "instance-2" ] );
|
||||
});
|
||||
|
||||
it('#remove_by_name - removing "instance-1" from "baz" should result in "baz" having just "instance-2"', function () {
|
||||
tor_pool.groups["baz"].remove_by_name('instance-1');
|
||||
|
||||
assert.deepEqual(get_instance_names("baz"), [ "instance-2" ] );
|
||||
});
|
||||
|
||||
it('#remove_at - removing "instance-1" from "baz" should result in "baz" having just "instance-2"', function () {
|
||||
tor_pool.groups["baz"].add_by_name('instance-1');
|
||||
tor_pool.groups["baz"].remove_at(0);
|
||||
|
||||
assert.deepEqual(get_instance_names("baz"), [ "instance-2" ] );
|
||||
});
|
||||
|
||||
after('shutdown tor pool', async function () { await tor_pool.exit(); });
|
||||
});
|
||||
});
|
Loading…
Reference in a new issue