548 lines
No EOL
18 KiB
JavaScript
548 lines
No EOL
18 KiB
JavaScript
|
|
const _ = require('lodash');
|
|
const assert = require('chai').assert;
|
|
const Promise = require('bluebird');
|
|
const { Provider } = require('nconf');
|
|
const nconf = new Provider();
|
|
const rpc = require('jrpc2');
|
|
const getPort = require('get-port');
|
|
const temp = require('temp');
|
|
const fs = require('fs');
|
|
|
|
nconf.use('memory');
|
|
require(`${__dirname}/../src/nconf_load_env.js`)(nconf);
|
|
nconf.defaults(require(`${__dirname}/../src/default_config.js`));
|
|
const { ControlServer } = require('../');
|
|
const { WAIT_FOR_CREATE } = require('./constants');
|
|
Promise.promisifyAll(fs);
|
|
Promise.promisifyAll(temp);
|
|
|
|
let rpcControlServer = new ControlServer(nconf);
|
|
let rpcControlPort;
|
|
let rpcClient;
|
|
|
|
describe('ControlServer - RPC Interface', function () {
|
|
before('setup control server', async function () {
|
|
rpcControlPort = await getPort();
|
|
await rpcControlServer.listen(rpcControlPort);
|
|
rpcClient = new rpc.Client(new rpc.tcpTransport({ port: rpcControlPort, hostname: 'localhost' }));
|
|
Promise.promisifyAll(rpcClient);
|
|
});
|
|
|
|
describe('#createInstances(number_of_instances)', function () {
|
|
this.timeout(WAIT_FOR_CREATE*2);
|
|
it('should create an instance', async function () {
|
|
await rpcClient.invokeAsync('createInstances', [{ Name: 'instance-1', Group: "foo" }]);
|
|
});
|
|
});
|
|
|
|
describe('#queryInstanceNames()', function () {
|
|
it("should have an instance named \"instance-1\"", async function () {
|
|
let raw = await rpcClient.invokeAsync('queryInstanceNames', [ ]);
|
|
|
|
let instances = JSON.parse(raw).result;
|
|
|
|
assert.deepEqual(instances, [ 'instance-1' ]);
|
|
});
|
|
});
|
|
|
|
describe('#queryGroupNames()', function () {
|
|
it("should have a group named \"foo\"", async function () {
|
|
let raw = await rpcClient.invokeAsync('queryGroupNames', [ ]);
|
|
|
|
let groups = JSON.parse(raw).result;
|
|
|
|
assert.deepEqual(groups, [ 'foo' ]);
|
|
});
|
|
});
|
|
|
|
describe('#queryInstancesByGroup()', function () {
|
|
it("should return an instance named \"instance-1\"", async function () {
|
|
let raw = await rpcClient.invokeAsync('queryInstancesByGroup', [ 'foo' ]);
|
|
|
|
let instances = JSON.parse(raw).result;
|
|
|
|
assert.equal(instances.length, 1);
|
|
assert.ok(instances[0]);
|
|
assert.equal(instances[0].name, 'instance-1');
|
|
});
|
|
});
|
|
|
|
describe('#queryInstances()', function () {
|
|
this.timeout(3000);
|
|
it('should return a list of instances', async function () {
|
|
let raw = await rpcClient.invokeAsync('queryInstances', []);
|
|
|
|
let instances = JSON.parse(raw).result;
|
|
|
|
assert.isArray(instances, 'Did not return an array');
|
|
assert.isNotEmpty(instances, 'Returned an empty array');
|
|
assert.isTrue(instances.every((instance) => ( typeof(instance.name) !== 'undefined' ) && ( instance.name !== null )), 'Objects were not valid');
|
|
});
|
|
});
|
|
|
|
describe('#addInstances(definitions)', function () {
|
|
this.timeout(WAIT_FOR_CREATE);
|
|
it("should add an instance based on a defintion", async function () {
|
|
let def = {
|
|
Name: 'instance-2',
|
|
Group: 'bar'
|
|
};
|
|
await rpcClient.invokeAsync('addInstances', [ def ]);
|
|
});
|
|
|
|
it("tor pool should now contain and instance that has the same name as the name specified in the defintion", function () {
|
|
assert.ok(rpcControlServer.tor_pool.instance_by_name('instance-2'));
|
|
});
|
|
});
|
|
|
|
describe('#queryInstanceByName(instance_name)', function () {
|
|
this.timeout(3000);
|
|
it('should return a single instance by name', async function () {
|
|
let raw = await rpcClient.invokeAsync('queryInstanceByName', ['instance-1']);
|
|
|
|
let instance = JSON.parse(raw).result;
|
|
|
|
assert.isOk(instance);
|
|
});
|
|
});
|
|
|
|
describe('#queryInstanceAt(index)', function () {
|
|
this.timeout(3000);
|
|
it('should return a single instance by index', async function () {
|
|
let raw = await rpcClient.invokeAsync('queryInstanceAt', [0]);
|
|
|
|
let instance = JSON.parse(raw).result;
|
|
|
|
assert.isOk(instance);
|
|
});
|
|
});
|
|
|
|
describe('#addInstanceToGroupByName()', function () {
|
|
it(`should add "instance-1" to baz`, async function () {
|
|
await rpcClient.invokeAsync('addInstanceToGroupByName', [ 'baz', "instance-1" ]);
|
|
});
|
|
|
|
it('"instance-1" should be added to "baz"', function () {
|
|
assert.include(rpcControlServer.tor_pool.instances_by_group('baz').map((i) => i.instance_name), "instance-1");
|
|
});
|
|
|
|
after('remove from group', function () {
|
|
rpcControlServer.tor_pool.groups['baz'].remove_by_name('instance-1');
|
|
});
|
|
});
|
|
|
|
describe('#addInstanceToGroupAt()', function () {
|
|
it(`should add "instance-1" to baz`, async function () {
|
|
await rpcClient.invokeAsync('addInstanceToGroupAt', [ 'baz', 0 ]);
|
|
});
|
|
|
|
it('"instance-1" should be added to "baz"', function () {
|
|
assert.include(rpcControlServer.tor_pool.instances_by_group('baz').map((i) => i.instance_name), "instance-1");
|
|
});
|
|
|
|
after('remove from group', function () {
|
|
rpcControlServer.tor_pool.groups['baz'].remove_by_name('instance-1');
|
|
});
|
|
});
|
|
|
|
describe('#removeInstanceFromGroupByName()', function () {
|
|
before('add to group', function () {
|
|
rpcControlServer.tor_pool.groups['baz'].add_by_name('instance-1');
|
|
});
|
|
|
|
it(`should remove "instance-1" from baz`, async function () {
|
|
await rpcClient.invokeAsync('removeInstanceFromGroupByName', [ 'baz', "instance-1" ]);
|
|
});
|
|
|
|
it('"instance-1" should be remove from to "baz"', function () {
|
|
assert.notInclude(rpcControlServer.tor_pool.group_names, "baz");
|
|
});
|
|
});
|
|
|
|
describe('#removeInstanceFromGroupAt()', function () {
|
|
before('add to group', function () {
|
|
rpcControlServer.tor_pool.groups['baz'].add_by_name('instance-1');
|
|
});
|
|
|
|
it(`should remove "instance-1" from baz`, async function () {
|
|
await rpcClient.invokeAsync('removeInstanceFromGroupAt', [ 'baz', 0 ]);
|
|
});
|
|
|
|
it('"instance-1" should be remove from to "baz"', function () {
|
|
assert.notInclude(rpcControlServer.tor_pool.group_names, "baz");
|
|
});
|
|
});
|
|
|
|
describe('#newIdentites()', function () {
|
|
this.timeout(3000);
|
|
it('should request new identities for all instances', async function () {
|
|
await rpcClient.invokeAsync('newIdentites', []);
|
|
});
|
|
});
|
|
|
|
describe('#newIdentityByName(instance_name)', function () {
|
|
this.timeout(3000);
|
|
it('should request new identities for all instances', async function () {
|
|
await rpcClient.invokeAsync('newIdentityByName', ['instance-1']);
|
|
});
|
|
});
|
|
|
|
describe('#newIdentityAt(index)', function () {
|
|
this.timeout(3000);
|
|
it('should request new identities for all instances', async function () {
|
|
await rpcClient.invokeAsync('newIdentityAt', [0]);
|
|
});
|
|
});
|
|
|
|
|
|
describe('#newIdentitiesByGroup()', function () {
|
|
it(`should get new identites for all instances in group`, async function () {
|
|
await rpcClient.invokeAsync('newIdentitiesByGroup', [ 'foo' ]);
|
|
});
|
|
});
|
|
|
|
describe("#setTorConfig(config_object)", function () {
|
|
this.timeout(3000);
|
|
it('should set several config variables on all instances', async function () {
|
|
await rpcClient.invokeAsync('setTorConfig', [ { TestSocks: 1, ProtocolWarnings: 1 } ]);
|
|
});
|
|
|
|
it('all instances should have the modified variables', async function() {
|
|
await Promise.all(rpcControlServer.tor_pool.instances.map(async (instance) => {
|
|
let var1 = await instance.get_config('TestSocks');
|
|
let var2 = await instance.get_config('ProtocolWarnings');
|
|
|
|
assert.equal(var1, 1);
|
|
assert.equal(var2, 1);
|
|
}));
|
|
});
|
|
|
|
after('unset config variables', async function () {
|
|
await rpcControlServer.tor_pool.set_config_all('TestSocks', 0);
|
|
await rpcControlServer.tor_pool.set_config_all('ProtocolWarnings', 0);
|
|
});
|
|
});
|
|
|
|
describe('#setConfig(key, value)', function () {
|
|
it('should set the default config of new instances', async function () {
|
|
this.timeout(3000);
|
|
await rpcClient.invokeAsync('setConfig', [ 'foo', 'bar' ]);
|
|
});
|
|
|
|
it('a new instance should be created with the modified property', function () {
|
|
assert.equal(nconf.get('foo'), 'bar');;
|
|
});
|
|
|
|
after('remove instance', function () {
|
|
nconf.reset();
|
|
});
|
|
});
|
|
|
|
describe('#setTorConfigByGroup()', function () {
|
|
it(`should set the config value on all instances`, async function () {
|
|
await rpcClient.invokeAsync('setTorConfigByGroup', [ 'foo', { 'ProtocolWarnings': 1 } ]);
|
|
});
|
|
|
|
it('all instances should have the config value set', async function () {
|
|
let values = _.flatten(await Promise.all(rpcControlServer.tor_pool.instances_by_group('foo').map((i) => i.get_config('ProtocolWarnings'))));
|
|
|
|
assert.isTrue(values.every((v) => v === "1"));
|
|
});
|
|
|
|
after('unset config values', async function () {
|
|
rpcControlServer.tor_pool.set_config_by_group('foo', 'ProtocolWarnings', 0);
|
|
});
|
|
});
|
|
|
|
describe('#getConfig()', function () {
|
|
before('set a property', function () {
|
|
nconf.set('foo', 'bar');
|
|
});
|
|
|
|
it('should return the property that was set', async function () {
|
|
this.timeout(6000);
|
|
let raw = await rpcClient.invokeAsync('getConfig', [ 'foo' ]);
|
|
let value = JSON.parse(raw).result;
|
|
|
|
assert.equal(value, 'bar');
|
|
});
|
|
|
|
after('unset property', function () {
|
|
nconf.reset();
|
|
});
|
|
});
|
|
|
|
describe('#saveConfig()', function () {
|
|
let file_path;
|
|
|
|
before('set a property and create temp file', async function () {
|
|
file_path = temp.path({ suffix: '.json' });
|
|
nconf.remove('memory');
|
|
nconf.file({ file: file_path });
|
|
nconf.set('foo', 'bar');
|
|
});
|
|
|
|
it('should save the config to the the temp file', async function () {
|
|
this.timeout(6000);
|
|
await rpcClient.invokeAsync('saveConfig', []);
|
|
});
|
|
|
|
it('the temp file should contain the property', async function () {
|
|
let tmp_file = await fs.readFileAsync(file_path, 'utf8');
|
|
let tmp_json = JSON.parse(tmp_file);
|
|
|
|
assert.equal(tmp_json.foo, 'bar');
|
|
});
|
|
|
|
after('unset property and delete file', async function () {
|
|
nconf.remove('file');
|
|
nconf.use('memory');
|
|
nconf.reset();
|
|
|
|
await fs.unlinkAsync(file_path);
|
|
});
|
|
});
|
|
|
|
describe('#loadConfig()', function () {
|
|
let file;
|
|
|
|
before('create temp file with property', async function () {
|
|
file = await temp.openAsync({ suffix: '.json' });
|
|
|
|
await fs.writeFileAsync(file.fd, JSON.stringify({ foo: 'bar' }));
|
|
|
|
nconf.remove('memory');
|
|
nconf.file({ file: file.path });
|
|
});
|
|
|
|
it('should load the config from the the temp file', async function () {
|
|
this.timeout(6000);
|
|
await rpcClient.invokeAsync('loadConfig', []);
|
|
});
|
|
|
|
it("the application's config should contain the property", async function () {
|
|
assert.equal(nconf.get('foo'), 'bar');
|
|
});
|
|
|
|
after('unset property and delete file', async function () {
|
|
nconf.remove('file');
|
|
nconf.use('memory');
|
|
nconf.reset();
|
|
|
|
await fs.unlinkAsync(file.path);
|
|
});
|
|
});
|
|
|
|
describe('#getLoadBalanceMethod()', function () {
|
|
this.timeout(3000);
|
|
before(function () {
|
|
rpcControlServer.tor_pool.load_balance_method = 'round_robin';
|
|
});
|
|
|
|
it('should return the current load balance method', async function () {
|
|
let raw = await rpcClient.invokeAsync('getLoadBalanceMethod', []);
|
|
let lb_method = JSON.parse(raw).result;
|
|
assert.equal(lb_method, 'round_robin');
|
|
});
|
|
});
|
|
|
|
describe('#setLoadBalanceMethod(load_balance_method)', function () {
|
|
this.timeout(3000);
|
|
|
|
it('should set the load balance method', async function () {
|
|
await rpcClient.invokeAsync('setLoadBalanceMethod', ['weighted']);
|
|
});
|
|
|
|
it('the load balance method should be changed', function () {
|
|
assert.equal(rpcControlServer.tor_pool.load_balance_method, 'weighted');
|
|
});
|
|
|
|
after(function () {
|
|
rpcControlServer.tor_pool.load_balance_method = 'round_robin';
|
|
});
|
|
});
|
|
|
|
describe("#getInstanceConfigByName(instance_name)", function () {
|
|
this.timeout(3000);
|
|
|
|
before('set config property', async function () {
|
|
await rpcControlServer.tor_pool.instance_by_name('instance-1').set_config('TestSocks', 1);
|
|
});
|
|
|
|
it('should retrieve the property from the tor instance', async function () {
|
|
let raw = await rpcClient.invokeAsync('getInstanceConfigByName', ['instance-1', "TestSocks"]);
|
|
let values = JSON.parse(raw).result;
|
|
|
|
assert.isNotEmpty(values);
|
|
assert.equal(values[0], "1");
|
|
});
|
|
|
|
after('unset config property', async function () {
|
|
await rpcControlServer.tor_pool.instance_by_name('instance-1').set_config('TestSocks', 0);
|
|
});
|
|
});
|
|
|
|
describe("#getInstanceConfigAt(index)", function () {
|
|
this.timeout(3000);
|
|
|
|
before('set config property', async function () {
|
|
await rpcControlServer.tor_pool.instance_at(0).set_config('TestSocks', 1);
|
|
});
|
|
|
|
it('should retrieve the property from the tor instance', async function () {
|
|
let raw = await rpcClient.invokeAsync('getInstanceConfigAt', [0, "TestSocks"]);
|
|
let values = JSON.parse(raw).result;
|
|
|
|
assert.isNotEmpty(values);
|
|
assert.equal(values[0], "1");
|
|
});
|
|
|
|
after('unset config property', async function () {
|
|
await rpcControlServer.tor_pool.instance_at(0).set_config('TestSocks', 0);
|
|
});
|
|
});
|
|
|
|
describe("#setInstanceConfigByName(instance_name)", function () {
|
|
this.timeout(3000);
|
|
|
|
before('set config property', async function () {
|
|
await rpcControlServer.tor_pool.instance_by_name('instance-1').set_config('TestSocks', 0);
|
|
});
|
|
|
|
it('should set the property for the tor instance', async function () {
|
|
await rpcClient.invokeAsync('setInstanceConfigByName', ['instance-1', 'TestSocks', 1]);
|
|
});
|
|
|
|
it('tor instance should have the modified property', async function () {
|
|
let value = await rpcControlServer.tor_pool.instance_by_name('instance-1').get_config('TestSocks');
|
|
assert.equal(value, 1);
|
|
});
|
|
|
|
after('unset config property', async function () {
|
|
await rpcControlServer.tor_pool.instance_by_name('instance-1').set_config('TestSocks', 0);
|
|
});
|
|
});
|
|
|
|
describe("#setInstanceConfigAt(index)", function () {
|
|
this.timeout(3000);
|
|
|
|
before('set config property', async function () {
|
|
await rpcControlServer.tor_pool.instance_at(0).set_config('TestSocks', 0);
|
|
});
|
|
|
|
it('should set the property for the tor instance', async function () {
|
|
await rpcClient.invokeAsync('setInstanceConfigAt', [0, 'TestSocks', 1]);
|
|
});
|
|
|
|
it('tor instance should have the modified property', async function () {
|
|
let value = await rpcControlServer.tor_pool.instance_at(0).get_config('TestSocks');
|
|
assert.equal(value, 1);
|
|
});
|
|
|
|
after('unset config property', async function () {
|
|
await rpcControlServer.tor_pool.instance_at(0).set_config('TestSocks', 0);
|
|
});
|
|
});
|
|
|
|
describe('#signalAllInstances(signal)', function () {
|
|
this.timeout(3000);
|
|
it('should signal to all interfaces', async function () {
|
|
await rpcClient.invokeAsync('signalAllInstances', [ 'DEBUG' ]);
|
|
});
|
|
});
|
|
|
|
describe('#signalInstanceAt(signal)', function () {
|
|
this.timeout(3000);
|
|
it('should signal to all interfaces', async function () {
|
|
await rpcClient.invokeAsync('signalInstanceAt', [ 0, 'DEBUG' ]);
|
|
});
|
|
});
|
|
|
|
describe('#signalAllInstances(signal)', function () {
|
|
this.timeout(3000);
|
|
it('should signal to all interfaces', async function () {
|
|
await rpcClient.invokeAsync('signalInstanceByName', [ 'instance-1', 'DEBUG' ]);
|
|
});
|
|
});
|
|
|
|
describe('#signalInstancesByGroup()', function () {
|
|
it(`should get new identites for all instances in group`, async function () {
|
|
await rpcClient.invokeAsync('signalInstancesByGroup', [ 'foo', 'DEBUG' ]);
|
|
});
|
|
});
|
|
|
|
describe("#nextInstance()", function () {
|
|
this.timeout(3000);
|
|
let instance_name;
|
|
it('should rotate the 0th item in the instances array', async function () {
|
|
instance_name = rpcControlServer.tor_pool.instances[0].instance_name;
|
|
await rpcClient.invokeAsync('nextInstance', []);
|
|
});
|
|
|
|
it('0th item in the instances array should be different after nextInstance is called', function () {
|
|
assert.notEqual(rpcControlServer.tor_pool.instances[0].instance_name, instance_name);
|
|
});
|
|
});
|
|
|
|
describe('#nextInstanceByGroup(group)', function () {
|
|
before('add "instance-1" to "foo"', function () {
|
|
rpcControlServer.tor_pool.add_instance_to_group_by_name('foo', 'instance-2');
|
|
});
|
|
|
|
it('should rotate the instances in group "foo"', async function () {
|
|
this.timeout(5000);
|
|
let first_instance_name_before = rpcControlServer.tor_pool.groups['foo'][0].instance_name;
|
|
await rpcClient.invokeAsync('nextInstanceByGroup', [ 'foo' ]);
|
|
let first_instance_name_after = rpcControlServer.tor_pool.groups['foo'][0].instance_name;
|
|
|
|
assert.notEqual(first_instance_name_after, first_instance_name_before);
|
|
});
|
|
|
|
after('remove "instance-1" from "foo"', function () {
|
|
rpcControlServer.tor_pool.remove_instance_from_group_by_name('foo', 'instance-2');
|
|
})
|
|
});
|
|
|
|
var instance_num1, instance_num2, i_num;
|
|
describe('#removeInstanceAt(index)', function () {
|
|
this.timeout(10000);
|
|
it("should remove an instance at the position specified", async function () {
|
|
instance_num1 = rpcControlServer.tor_pool.instances.length;
|
|
await rpcClient.invokeAsync('removeInstanceAt', [0]);
|
|
});
|
|
|
|
it('the tor pool should contain one instance fewer', function () {
|
|
assert.equal(rpcControlServer.tor_pool.instances.length, (instance_num1 - 1));
|
|
});
|
|
});
|
|
|
|
describe('#removeInstanceByName(instance_name)', function () {
|
|
this.timeout(10000);
|
|
it("should remove an instance at the position specified", async function () {
|
|
instance_num2 = rpcControlServer.tor_pool.instances.length;
|
|
await rpcClient.invokeAsync('removeInstanceByName', [ "instance-1" ]);
|
|
});
|
|
|
|
it('the tor pool should contain one instance fewer', function () {
|
|
assert.equal(rpcControlServer.tor_pool.instances.length, (instance_num2 - 1));
|
|
});
|
|
});
|
|
|
|
describe('#closeInstances()', function () {
|
|
this.timeout(10000);
|
|
it('should shutdown all instances', async function () {
|
|
instance_num = rpcControlServer.tor_pool.instances.length;
|
|
await rpcClient.invokeAsync('closeInstances', [ ]);
|
|
});
|
|
|
|
it('no instances should be present in the pool', function () {
|
|
assert.equal(rpcControlServer.tor_pool.instances.length, 0);
|
|
});
|
|
});
|
|
|
|
after('shutdown tor pool', async function () {
|
|
this.timeout(10000);
|
|
await rpcControlServer.tor_pool.exit();
|
|
});
|
|
}); |