PHP WebShell

Текущая директория: /usr/lib/node_modules/bitgo-express/node_modules/ripple-lib/test

Просмотр файла: connection-test.js

'use strict'; // eslint-disable-line 
/* eslint-disable max-nested-callbacks */

const _ = require('lodash');
const net = require('net');
const assert = require('assert-diff');
const setupAPI = require('./setup-api');
const RippleAPI = require('ripple-api').RippleAPI;
const utils = RippleAPI._PRIVATE.ledgerUtils;
const ledgerClose = require('./fixtures/rippled/ledger-close.json');


const TIMEOUT = 200000;   // how long before each test case times out

function unused() {
}

function createServer() {
  return new Promise((resolve, reject) => {
    const server = net.createServer();
    server.on('listening', function() {
      resolve(server);
    });
    server.on('error', function(error) {
      reject(error);
    });
    server.listen(0, '0.0.0.0');
  });
}

describe('Connection', function() {
  this.timeout(TIMEOUT);
  beforeEach(setupAPI.setup);
  afterEach(setupAPI.teardown);

  it('default options', function() {
    const connection = new utils.common.Connection('url');
    assert.strictEqual(connection._url, 'url');
    assert(_.isUndefined(connection._proxyURL));
    assert(_.isUndefined(connection._authorization));
  });

  it('trace', function() {
    const connection = new utils.common.Connection('url', {trace: true});
    const message1 = '{"type": "transaction"}';
    const message2 = '{"type": "path_find"}';
    const messages = [];
    connection._console = {
      log: function(message) {
        messages.push(message);
      }
    };
    connection._ws = {
      send: function() {}
    };
    connection._onMessage(message1);
    connection._send(message2);

    assert.deepEqual(messages, [message1, message2]);
  });

  it('with proxy', function(done) {
    if (process.browser) {
      done();
      return;
    }
    createServer().then(server => {
      const port = server.address().port;
      const expect = 'CONNECT localhost';
      server.on('connection', socket => {
        socket.on('data', data => {
          const got = data.toString('ascii', 0, expect.length);
          assert.strictEqual(got, expect);
          server.close();
          done();
        });
      });

      const options = {
        proxy: 'ws://localhost:' + port,
        authorization: 'authorization',
        trustedCertificates: ['path/to/pem']
      };
      const connection =
        new utils.common.Connection(this.api.connection._url, options);
      connection.connect().catch(done);
      connection.connect().catch(done);
    }, done);
  });

  it('Multiply disconnect calls', function() {
    this.api.disconnect();
    return this.api.disconnect();
  });

  it('reconnect', function() {
    return this.api.connection.reconnect();
  });

  it('NotConnectedError', function() {
    const connection = new utils.common.Connection('url');
    return connection.getLedgerVersion().then(() => {
      assert(false, 'Should throw NotConnectedError');
    }).catch(error => {
      assert(error instanceof this.api.errors.NotConnectedError);
    });
  });

  it('should throw NotConnectedError if server not responding ', function(
    done
  ) {
    if (process.browser) {
      const phantomTest = /PhantomJS/;
      if (phantomTest.test(navigator.userAgent)) {
        // inside PhantomJS this one just hangs, so skip as not very relevant
        done();
        return;
      }
    }

    // Address where no one listens
    const connection =
      new utils.common.Connection('ws://testripple.circleci.com:129');
    connection.on('error', done);
    connection.connect().catch(error => {
      assert(error instanceof this.api.errors.NotConnectedError);
      done();
    });
  });

  it('DisconnectedError', function() {
    this.api.connection._send(JSON.stringify({
      command: 'config',
      data: {disconnectOnServerInfo: true}
    }));
    return this.api.getServerInfo().then(() => {
      assert(false, 'Should throw DisconnectedError');
    }).catch(error => {
      assert(error instanceof this.api.errors.DisconnectedError);
    });
  });

  it('TimeoutError', function() {
    this.api.connection._send = function() {
      return Promise.resolve({});
    };
    const request = {command: 'server_info'};
    return this.api.connection.request(request, 1).then(() => {
      assert(false, 'Should throw TimeoutError');
    }).catch(error => {
      assert(error instanceof this.api.errors.TimeoutError);
    });
  });

  it('DisconnectedError on send', function() {
    this.api.connection._ws.send = function(message, options, callback) {
      unused(message, options);
      callback({message: 'not connected'});
    };
    return this.api.getServerInfo().then(() => {
      assert(false, 'Should throw DisconnectedError');
    }).catch(error => {
      assert(error instanceof this.api.errors.DisconnectedError);
      assert.strictEqual(error.message, 'not connected');
    });
  });

  it('ResponseFormatError', function() {
    this.api.connection._send = function(message) {
      const parsed = JSON.parse(message);
      setTimeout(() => {
        this._ws.emit('message', JSON.stringify({
          id: parsed.id,
          type: 'response',
          status: 'unrecognized'
        }));
      }, 2);
      return new Promise(() => {});
    };
    return this.api.getServerInfo().then(() => {
      assert(false, 'Should throw ResponseFormatError');
    }).catch(error => {
      assert(error instanceof this.api.errors.ResponseFormatError);
    });
  });

  it('reconnect on unexpected close ', function(done) {
    this.api.connection.on('connected', () => {
      done();
    });

    setTimeout(() => {
      this.api.connection._ws.close();
    }, 1);
  });

  describe('reconnection test', function() {
    beforeEach(function() {
      this.api.connection.__workingUrl = this.api.connection._url;
      this.api.connection.__doReturnBad = function() {
        this._url = this.__badUrl;
        const self = this;
        function onReconnect(num) {
          if (num >= 2) {
            self._url = self.__workingUrl;
            self.removeListener('reconnecting', onReconnect);
          }
        }
        this.on('reconnecting', onReconnect);
      };
    });

    afterEach(function() {

    });

    it('reconnect on several unexpected close', function(done) {
      if (process.browser) {
        const phantomTest = /PhantomJS/;
        if (phantomTest.test(navigator.userAgent)) {
          // inside PhantomJS this one just hangs, so skip as not very relevant
          done();
          return;
        }
      }
      this.timeout(70001);
      const self = this;
      self.api.connection.__badUrl = 'ws://testripple.circleci.com:129';
      function breakConnection() {
        self.api.connection.__doReturnBad();
        self.api.connection._send(JSON.stringify({
          command: 'test_command',
          data: {disconnectIn: 10}
        }));
      }

      let connectsCount = 0;
      let disconnectsCount = 0;
      let reconnectsCount = 0;
      let code = 0;
      this.api.connection.on('reconnecting', () => {
        reconnectsCount += 1;
      });
      this.api.connection.on('disconnected', _code => {
        code = _code;
        disconnectsCount += 1;
      });
      const num = 3;
      this.api.connection.on('connected', () => {
        connectsCount += 1;
        if (connectsCount < num) {
          breakConnection();
        }
        if (connectsCount === num) {
          if (disconnectsCount !== num) {
            done(new Error('disconnectsCount must be equal to ' + num +
              '(got ' + disconnectsCount + ' instead)'));
          } else if (reconnectsCount !== num * 2) {
            done(new Error('reconnectsCount must be equal to ' + num * 2 +
              ' (got ' + reconnectsCount + ' instead)'));
          } else if (code !== 1006) {
            done(new Error('disconnect must send code 1006 (got ' + code +
              ' instead)'));
          } else {
            done();
          }
        }
      });

      breakConnection();
    });
  });

  it('should emit disconnected event with code 1000 (CLOSE_NORMAL)',
  function(done
  ) {
    this.api.once('disconnected', code => {
      assert.strictEqual(code, 1000);
      done();
    });
    this.api.disconnect();
  });

  it('should emit disconnected event with code 1006 (CLOSE_ABNORMAL)',
  function(done
  ) {
    this.api.once('error', error => {
      done(new Error('should not throw error, got ' + String(error)));
    });
    this.api.once('disconnected', code => {
      assert.strictEqual(code, 1006);
      done();
    });
    this.api.connection._send(JSON.stringify({
      command: 'test_command',
      data: {disconnectIn: 10}
    }));
  });

  it('should emit connected event on after reconnect', function(done) {
    this.api.once('connected', done);
    this.api.connection._ws.close();
  });

  it('Multiply connect calls', function() {
    return this.api.connect().then(() => {
      return this.api.connect();
    });
  });

  it('hasLedgerVersion', function() {
    return this.api.connection.hasLedgerVersion(8819951).then(result => {
      assert(result);
    });
  });

  it('Cannot connect because no server', function() {
    const connection = new utils.common.Connection();
    return connection.connect().then(() => {
      assert(false, 'Should throw ConnectionError');
    }).catch(error => {
      assert(error instanceof this.api.errors.ConnectionError);
    });
  });

  it('connect multiserver error', function() {
    const options = {
      servers: ['wss://server1.com', 'wss://server2.com']
    };
    assert.throws(function() {
      const api = new RippleAPI(options);
      unused(api);
    }, this.api.errors.RippleError);
  });

  it('connect throws error', function(done) {
    this.api.once('error', (type, info) => {
      assert.strictEqual(type, 'type');
      assert.strictEqual(info, 'info');
      done();
    });
    this.api.connection.emit('error', 'type', 'info');
  });

  it('emit stream messages', function(done) {
    let transactionCount = 0;
    let pathFindCount = 0;
    this.api.connection.on('transaction', () => {
      transactionCount++;
    });
    this.api.connection.on('path_find', () => {
      pathFindCount++;
    });
    this.api.connection.on('1', () => {
      assert.strictEqual(transactionCount, 1);
      assert.strictEqual(pathFindCount, 1);
      done();
    });

    this.api.connection._onMessage(JSON.stringify({
      type: 'transaction'
    }));
    this.api.connection._onMessage(JSON.stringify({
      type: 'path_find'
    }));
    this.api.connection._onMessage(JSON.stringify({
      type: 'response', id: 1
    }));
  });

  it('invalid message id', function(done) {
    this.api.on('error', (errorCode, errorMessage, message) => {
      assert.strictEqual(errorCode, 'badMessage');
      assert.strictEqual(errorMessage, 'valid id not found in response');
      assert.strictEqual(message,
        '{"type":"response","id":"must be integer"}');
      done();
    });
    this.api.connection._onMessage(JSON.stringify({
      type: 'response', id: 'must be integer'
    }));
  });

  it('propagate error message', function(done) {
    this.api.on('error', (errorCode, errorMessage, data) => {
      assert.strictEqual(errorCode, 'slowDown');
      assert.strictEqual(errorMessage, 'slow down');
      assert.deepEqual(data, {error: 'slowDown', error_message: 'slow down'});
      done();
    });
    this.api.connection._onMessage(JSON.stringify({
      error: 'slowDown', error_message: 'slow down'
    }));
  });

  it('unrecognized message type', function(done) {
    this.api.on('error', (errorCode, errorMessage, message) => {
      assert.strictEqual(errorCode, 'badMessage');
      assert.strictEqual(errorMessage, 'unrecognized message type: unknown');
      assert.strictEqual(message, '{"type":"unknown"}');
      done();
    });

    this.api.connection._onMessage(JSON.stringify({type: 'unknown'}));
  });

  it('ledger close without validated_ledgers', function(done) {
    const message = _.omit(ledgerClose, 'validated_ledgers');
    this.api.on('ledger', function(ledger) {
      assert.strictEqual(ledger.ledgerVersion, 8819951);
      done();
    });
    this.api.connection._ws.emit('message', JSON.stringify(message));
  });

  it('should throw RippledNotInitializedError if server does not have ' +
  'validated ledgers',
  function() {
    this.timeout(3000);

    this.api.connection._send(JSON.stringify({
      command: 'global_config',
      data: {returnEmptySubscribeRequest: 1}
    }));

    const api = new RippleAPI({server: this.api.connection._url});
    return api.connect().then(() => {
      assert(false, 'Must have thrown!');
    }, error => {
      assert(error instanceof this.api.errors.RippledNotInitializedError,
        'Must throw RippledNotInitializedError, got instead ' + String(error));
    });
  });

  it('should try to reconnect on empty subscribe response on reconnect',
  function(done) {
    this.timeout(23000);

    this.api.on('error', error => {
      done(error || new Error('Should not emit error.'));
    });
    let disconncedCount = 0;
    this.api.on('connected', () => {
      done(disconncedCount !== 1 ?
        new Error('Wrong number of disconnects') : undefined);
    });
    this.api.on('disconnected', () => {
      disconncedCount++;
    });

    this.api.connection._send(JSON.stringify({
      command: 'global_config',
      data: {returnEmptySubscribeRequest: 3}
    }));

    this.api.connection._send(JSON.stringify({
      command: 'test_command',
      data: {disconnectIn: 10}
    }));
  });
});

Выполнить команду


Для локальной разработки. Не используйте в интернете!