mirror of
				https://github.com/Xahau/xahaud.git
				synced 2025-11-04 10:45:50 +00:00 
			
		
		
		
	Revert system test changes:
* Revert "Shutdown rippled before http server in json rpc test to avoid http server potentially receiving messages due to automatic ledger close interval."
* Revert "Update ripple-lib integration tests"
This reverts commit 83442825e5.
			
			
This commit is contained in:
		@@ -10,7 +10,7 @@
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "ripple-lib": "0.7.31",
 | 
			
		||||
    "ripple-lib": "0.7.25",
 | 
			
		||||
    "async": "~0.2.9",
 | 
			
		||||
    "extend": "~1.2.0",
 | 
			
		||||
    "simple-jsonrpc": "~0.0.2",
 | 
			
		||||
@@ -31,4 +31,4 @@
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  "readmeFilename": "README.md"
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
@@ -50,10 +50,10 @@ function build_teardown() {
 | 
			
		||||
  return function (done) {
 | 
			
		||||
    var self  = this;
 | 
			
		||||
 | 
			
		||||
    teardown.call(self, function () {
 | 
			
		||||
      self.server.close(function () {
 | 
			
		||||
        done();
 | 
			
		||||
      });
 | 
			
		||||
    self.server.close(function () {
 | 
			
		||||
      // console.log("server closed");
 | 
			
		||||
 | 
			
		||||
      teardown.call(self, done);
 | 
			
		||||
    });
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -2,4 +2,4 @@
 | 
			
		||||
--compilers coffee:coffee-script
 | 
			
		||||
--ui tdd
 | 
			
		||||
--timeout 10000
 | 
			
		||||
--slow 600
 | 
			
		||||
--slow 600
 | 
			
		||||
@@ -1,314 +0,0 @@
 | 
			
		||||
var async       = require('async');
 | 
			
		||||
var assert      = require('assert');
 | 
			
		||||
var ripple      = require('ripple-lib');
 | 
			
		||||
var Amount      = require('ripple-lib').Amount;
 | 
			
		||||
var Remote      = require('ripple-lib').Remote;
 | 
			
		||||
var Transaction = require('ripple-lib').Transaction;
 | 
			
		||||
var Server      = require('./server').Server;
 | 
			
		||||
var testutils   = require('./testutils');
 | 
			
		||||
var config      = testutils.init_config();
 | 
			
		||||
 | 
			
		||||
suite('NoRipple', function() {
 | 
			
		||||
  var $ = { };
 | 
			
		||||
 | 
			
		||||
  setup(function(done) {
 | 
			
		||||
    testutils.build_setup().call($, done);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  teardown(function(done) {
 | 
			
		||||
    testutils.build_teardown().call($, done);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('set and clear NoRipple', function(done) {
 | 
			
		||||
    var self = this;
 | 
			
		||||
 | 
			
		||||
    var steps = [
 | 
			
		||||
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        self.what = 'Create accounts.';
 | 
			
		||||
        testutils.create_accounts($.remote, 'root', '10000.0', [ 'alice' ], callback);
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        self.what = 'Check a non-existent credit limit';
 | 
			
		||||
 | 
			
		||||
        $.remote.request_ripple_balance('alice', 'root', 'USD', 'CURRENT', function(err) {
 | 
			
		||||
          assert.strictEqual('remoteError', err.error);
 | 
			
		||||
          assert.strictEqual('entryNotFound', err.remote.error);
 | 
			
		||||
          callback();
 | 
			
		||||
        });
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        self.what = 'Create a credit limit with NoRipple flag';
 | 
			
		||||
 | 
			
		||||
        var tx = $.remote.transaction();
 | 
			
		||||
        tx.trustSet('root', '100/USD/alice');
 | 
			
		||||
        tx.setFlags('NoRipple');
 | 
			
		||||
 | 
			
		||||
        tx.once('error', callback);
 | 
			
		||||
        tx.once('proposed', function(res) {
 | 
			
		||||
          callback();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        tx.submit();
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        self.what = 'Check no-ripple sender';
 | 
			
		||||
 | 
			
		||||
        $.remote.requestAccountLines('root', void(0), 'CURRENT', function(err, m) {
 | 
			
		||||
          if (err) return callback(err);
 | 
			
		||||
          assert(typeof m === 'object');
 | 
			
		||||
          assert(Array.isArray(m.lines));
 | 
			
		||||
          assert(m.lines[0].no_ripple);
 | 
			
		||||
          callback();
 | 
			
		||||
        });
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        self.what = 'Check no-ripple destination';
 | 
			
		||||
 | 
			
		||||
        $.remote.requestAccountLines('alice', void(0), 'CURRENT', function(err, m) {
 | 
			
		||||
          if (err) return callback(err);
 | 
			
		||||
          assert(typeof m === 'object');
 | 
			
		||||
          assert(Array.isArray(m.lines));
 | 
			
		||||
          assert(m.lines[0].no_ripple_peer);
 | 
			
		||||
          callback();
 | 
			
		||||
        });
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        self.what = 'Create a credit limit with ClearNoRipple flag';
 | 
			
		||||
 | 
			
		||||
        var tx = $.remote.transaction();
 | 
			
		||||
        tx.trustSet('root', '100/USD/alice');
 | 
			
		||||
        tx.setFlags('ClearNoRipple');
 | 
			
		||||
 | 
			
		||||
        tx.once('error', callback);
 | 
			
		||||
        tx.once('proposed', function(res) {
 | 
			
		||||
          callback();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        tx.submit();
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        self.what = 'Check no-ripple cleared sender';
 | 
			
		||||
 | 
			
		||||
        $.remote.requestAccountLines('root', void(0), 'CURRENT', function(err, m) {
 | 
			
		||||
          if (err) return callback(err);
 | 
			
		||||
          assert(typeof m === 'object');
 | 
			
		||||
          assert(Array.isArray(m.lines));
 | 
			
		||||
          assert(!m.lines[0].no_ripple);
 | 
			
		||||
          callback();
 | 
			
		||||
        });
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        self.what = 'Check no-ripple cleared destination';
 | 
			
		||||
 | 
			
		||||
        $.remote.requestAccountLines('alice', void(0), 'CURRENT', function(err, m) {
 | 
			
		||||
          if (err) return callback(err);
 | 
			
		||||
          assert(typeof m === 'object');
 | 
			
		||||
          assert(Array.isArray(m.lines));
 | 
			
		||||
          assert(!m.lines[0].no_ripple_peer);
 | 
			
		||||
          callback();
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    async.series(steps, function(err) {
 | 
			
		||||
      assert(!err, self.what + ': ' + err);
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('set NoRipple on line with negative balance', function(done) {
 | 
			
		||||
    // Setting NoRipple on a line with negative balance should fail
 | 
			
		||||
    var self = this;
 | 
			
		||||
 | 
			
		||||
    var steps = [
 | 
			
		||||
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        self.what = 'Create accounts';
 | 
			
		||||
 | 
			
		||||
        testutils.create_accounts(
 | 
			
		||||
          $.remote,
 | 
			
		||||
          'root',
 | 
			
		||||
          '10000.0',
 | 
			
		||||
          [ 'alice', 'bob', 'carol' ],
 | 
			
		||||
          callback);
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        self.what = 'Set credit limits';
 | 
			
		||||
 | 
			
		||||
        testutils.credit_limits($.remote, {
 | 
			
		||||
          bob: '100/USD/alice',
 | 
			
		||||
          carol: '100/USD/bob'
 | 
			
		||||
        }, callback);
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        self.what = 'Payment';
 | 
			
		||||
 | 
			
		||||
        var tx = $.remote.transaction();
 | 
			
		||||
        tx.buildPath(true);
 | 
			
		||||
        tx.payment('alice', 'carol', '50/USD/carol');
 | 
			
		||||
 | 
			
		||||
        tx.once('submitted', function(m) {
 | 
			
		||||
          assert.strictEqual(m.engine_result, 'tesSUCCESS');
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        tx.submit(callback);
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        self.what = 'Set NoRipple alice';
 | 
			
		||||
 | 
			
		||||
        var tx = $.remote.transaction();
 | 
			
		||||
        tx.trustSet('alice', '100/USD/bob');
 | 
			
		||||
        tx.setFlags('NoRipple');
 | 
			
		||||
 | 
			
		||||
        tx.once('submitted', function(m) {
 | 
			
		||||
          assert.strictEqual(m.engine_result, 'tesSUCCESS');
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        tx.submit(callback);
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        self.what = 'Set NoRipple carol';
 | 
			
		||||
 | 
			
		||||
        var tx = $.remote.transaction();
 | 
			
		||||
        tx.trustSet('bob', '100/USD/carol');
 | 
			
		||||
        tx.setFlags('NoRipple');
 | 
			
		||||
 | 
			
		||||
        tx.once('submitted', function(m) {
 | 
			
		||||
          assert.strictEqual(m.engine_result, 'tesSUCCESS');
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        tx.submit(callback);
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        self.what = 'Find path alice > carol';
 | 
			
		||||
 | 
			
		||||
        var request = $.remote.requestRipplePathFind('alice', 'carol', '1/USD/carol', [ { currency: 'USD' } ]);
 | 
			
		||||
        request.callback(function(err, paths) {
 | 
			
		||||
          assert.ifError(err);
 | 
			
		||||
          assert(Array.isArray(paths.alternatives));
 | 
			
		||||
          assert.strictEqual(paths.alternatives.length, 1);
 | 
			
		||||
          callback();
 | 
			
		||||
        });
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        $.remote.requestAccountLines('alice', function(err, res) {
 | 
			
		||||
          assert.ifError(err);
 | 
			
		||||
          assert.strictEqual(typeof res, 'object');
 | 
			
		||||
          assert(Array.isArray(res.lines));
 | 
			
		||||
          assert.strictEqual(res.lines.length, 1);
 | 
			
		||||
          assert(!(res.lines[0].no_ripple));
 | 
			
		||||
          callback();
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    async.series(steps, function(error) {
 | 
			
		||||
      assert(!error, self.what + ': ' + error);
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('pairwise NoRipple', function(done) {
 | 
			
		||||
    var self = this;
 | 
			
		||||
 | 
			
		||||
    var steps = [
 | 
			
		||||
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        self.what = 'Create accounts';
 | 
			
		||||
 | 
			
		||||
        testutils.create_accounts(
 | 
			
		||||
          $.remote,
 | 
			
		||||
          'root',
 | 
			
		||||
          '10000.0',
 | 
			
		||||
          [ 'alice', 'bob', 'carol' ],
 | 
			
		||||
          callback);
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        self.what = 'Set credit limits';
 | 
			
		||||
 | 
			
		||||
        testutils.credit_limits($.remote, {
 | 
			
		||||
          bob: '100/USD/alice',
 | 
			
		||||
          carol: '100/USD/bob'
 | 
			
		||||
        }, callback);
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        self.what = 'Set NoRipple alice';
 | 
			
		||||
 | 
			
		||||
        var tx = $.remote.transaction();
 | 
			
		||||
        tx.trustSet('bob', '100/USD/alice');
 | 
			
		||||
        tx.setFlags('NoRipple');
 | 
			
		||||
 | 
			
		||||
        tx.once('submitted', function(m) {
 | 
			
		||||
          assert.strictEqual(m.engine_result, 'tesSUCCESS');
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        tx.submit(callback);
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        self.what = 'Set NoRipple carol';
 | 
			
		||||
 | 
			
		||||
        var tx = $.remote.transaction();
 | 
			
		||||
        tx.trustSet('bob', '100/USD/carol');
 | 
			
		||||
        tx.setFlags('NoRipple');
 | 
			
		||||
 | 
			
		||||
        tx.once('submitted', function(m) {
 | 
			
		||||
          assert.strictEqual(m.engine_result, 'tesSUCCESS');
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        tx.submit(callback);
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        self.what = 'Find path alice > carol';
 | 
			
		||||
 | 
			
		||||
        var request = $.remote.requestRipplePathFind('alice', 'carol', '1/USD/carol', [ { currency: 'USD' } ]);
 | 
			
		||||
        request.callback(function(err, paths) {
 | 
			
		||||
          assert.ifError(err);
 | 
			
		||||
          assert(Array.isArray(paths.alternatives));
 | 
			
		||||
          assert.strictEqual(paths.alternatives.length, 0);
 | 
			
		||||
          callback();
 | 
			
		||||
        });
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        self.what = 'Payment';
 | 
			
		||||
 | 
			
		||||
        var tx = $.remote.transaction();
 | 
			
		||||
        tx.buildPath(true);
 | 
			
		||||
        tx.payment('alice', 'carol', '1/USD/carol');
 | 
			
		||||
 | 
			
		||||
        tx.once('submitted', function(m) {
 | 
			
		||||
          assert.strictEqual(m.engine_result, 'tecPATH_DRY');
 | 
			
		||||
          callback();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        tx.submit();
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    async.series(steps, function(error) {
 | 
			
		||||
      assert(!error, self.what + ': ' + error);
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
@@ -1,444 +0,0 @@
 | 
			
		||||
var async       = require('async');
 | 
			
		||||
var assert      = require('assert');
 | 
			
		||||
var ripple      = require('ripple-lib');
 | 
			
		||||
var Amount      = require('ripple-lib').Amount;
 | 
			
		||||
var Remote      = require('ripple-lib').Remote;
 | 
			
		||||
var Transaction = require('ripple-lib').Transaction;
 | 
			
		||||
var Server      = require('./server').Server;
 | 
			
		||||
var testutils   = require('./testutils');
 | 
			
		||||
var config      = testutils.init_config();
 | 
			
		||||
 | 
			
		||||
suite('Robust transaction submission', function() {
 | 
			
		||||
  var $ = { };
 | 
			
		||||
 | 
			
		||||
  setup(function(done) {
 | 
			
		||||
    testutils.build_setup().call($, function() {
 | 
			
		||||
      $.remote.local_signing = true;
 | 
			
		||||
      $.remote.request_subscribe()
 | 
			
		||||
      .accounts($.remote.account('root')._account_id)
 | 
			
		||||
      .callback(done);
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  teardown(function(done) {
 | 
			
		||||
    testutils.build_teardown().call($, done);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  // Payment is submitted (without a destination tag)
 | 
			
		||||
  // to a destination which requires one.
 | 
			
		||||
  //
 | 
			
		||||
  // The sequence is now in the future.
 | 
			
		||||
  //
 | 
			
		||||
  // Immediately subsequent transactions should err
 | 
			
		||||
  // with terPRE_SEQ.
 | 
			
		||||
  //
 | 
			
		||||
  // Gaps in the sequence should be filled with an
 | 
			
		||||
  // empty transaction.
 | 
			
		||||
  //
 | 
			
		||||
  // Transaction should ultimately succeed.
 | 
			
		||||
  //
 | 
			
		||||
  // Subsequent transactions should be submitted with
 | 
			
		||||
  // an up-to-date transction sequence. i.e. the
 | 
			
		||||
  // internal sequence should always catch up.
 | 
			
		||||
 | 
			
		||||
  test('sequence realignment', function(done) {
 | 
			
		||||
    var self = this;
 | 
			
		||||
 | 
			
		||||
    self.sent_transactions = [ ];
 | 
			
		||||
 | 
			
		||||
    var steps = [
 | 
			
		||||
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        self.what = 'Create accounts';
 | 
			
		||||
        testutils.create_accounts($.remote, 'root', '20000.0', [ 'alice', 'bob' ], callback);
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        self.what = 'Set RequireDestTag';
 | 
			
		||||
 | 
			
		||||
        var tx = $.remote.transaction().account_set('alice');
 | 
			
		||||
        tx.set_flags('RequireDestTag');
 | 
			
		||||
 | 
			
		||||
        tx.once('submitted', function(m) {
 | 
			
		||||
          assert.strictEqual('tesSUCCESS', m.engine_result);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        tx.submit(callback);
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        $.remote.getAccount('root').on('transaction-outbound', function(tx) {
 | 
			
		||||
          if (tx.transaction.TransactionType === 'Payment' && tx.transaction.Amount === '1000000') {
 | 
			
		||||
            self.sent_transactions.push(tx.transaction);
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
        setTimeout(callback, 100);
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        self.what = 'Send transaction without a destination tag';
 | 
			
		||||
 | 
			
		||||
        var tx = $.remote.transaction().payment({
 | 
			
		||||
          from: 'root',
 | 
			
		||||
          to: 'alice',
 | 
			
		||||
          amount: Amount.from_human('1XRP')
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        tx.once('submitted', function(m) {
 | 
			
		||||
          assert.strictEqual('tefDST_TAG_NEEDED', m.engine_result);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        tx.submit();
 | 
			
		||||
 | 
			
		||||
        //Invoke callback immediately
 | 
			
		||||
        callback();
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        self.what = 'Send normal transaction which should succeed';
 | 
			
		||||
 | 
			
		||||
        var tx = $.remote.transaction().payment({
 | 
			
		||||
          from: 'root',
 | 
			
		||||
          to: 'bob',
 | 
			
		||||
          amount: Amount.from_human('1XRP')
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        //First attempt at submission should result in
 | 
			
		||||
        //terPRE_SEQ as the sequence is still in the future
 | 
			
		||||
        tx.once('submitted', function(m) {
 | 
			
		||||
          assert.strictEqual('terPRE_SEQ', m.engine_result);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        tx.once('resubmitted', function() {
 | 
			
		||||
          self.resubmitted = true;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        tx.submit(callback);
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        self.what = 'Send another normal transaction which should succeed';
 | 
			
		||||
 | 
			
		||||
        var tx = $.remote.transaction().payment({
 | 
			
		||||
          from: 'root',
 | 
			
		||||
          to: 'bob',
 | 
			
		||||
          amount: Amount.from_human('1XRP')
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        tx.once('submitted', function(m) {
 | 
			
		||||
          assert.strictEqual(m.engine_result, 'tesSUCCESS');
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        tx.submit(callback);
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        setTimeout(callback, 1000 * 2);
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function checkPending(callback) {
 | 
			
		||||
        assert.strictEqual($.remote.getAccount('root')._transactionManager._pending.length(), 0, 'Pending transactions persisting');
 | 
			
		||||
        callback();
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        testutils.verify_balance($.remote, 'bob', '20002000000', callback);
 | 
			
		||||
      }
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    async.series(steps, function(err) {
 | 
			
		||||
      assert(!err, self.what + ': ' + err);
 | 
			
		||||
 | 
			
		||||
      assert(self.resubmitted, 'Transaction failed to resubmit');
 | 
			
		||||
 | 
			
		||||
      assert(self.sent_transactions.length, 'No payments sent');
 | 
			
		||||
 | 
			
		||||
      assert.strictEqual(self.sent_transactions.length, 2, 'Payment submitted more than once');
 | 
			
		||||
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  // Submit a normal payment which should succeed.
 | 
			
		||||
  //
 | 
			
		||||
  // Remote disconnects immediately after submission
 | 
			
		||||
  // and before the validated transaction result is
 | 
			
		||||
  // received.
 | 
			
		||||
  //
 | 
			
		||||
  // Remote reconnects in the future. During this
 | 
			
		||||
  // time it is presumed that the transaction should
 | 
			
		||||
  // have succeeded, but an immediate response was
 | 
			
		||||
  // not possible, as the server was disconnected.
 | 
			
		||||
  //
 | 
			
		||||
  // Upon reconnection, recent account transaction
 | 
			
		||||
  // history is loaded.
 | 
			
		||||
  //
 | 
			
		||||
  // The submitted transaction should be detected,
 | 
			
		||||
  // and the transaction should ultimately succeed.
 | 
			
		||||
 | 
			
		||||
  test('temporary server disconnection', function(done) {
 | 
			
		||||
    var self = this;
 | 
			
		||||
 | 
			
		||||
    self.sent_transactions = [ ];
 | 
			
		||||
 | 
			
		||||
    var steps = [
 | 
			
		||||
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        self.what = 'Create accounts';
 | 
			
		||||
        testutils.create_accounts($.remote, 'root', '20000.0', [ 'alice' ], callback);
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        $.remote.getAccount('root').on('transaction-outbound', function(tx) {
 | 
			
		||||
          if (tx.transaction.TransactionType === 'Payment' && tx.transaction.Amount === '1000000') {
 | 
			
		||||
            self.sent_transactions.push(tx.transaction);
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
        setTimeout(callback, 100);
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        self.what = 'Submit a transaction';
 | 
			
		||||
 | 
			
		||||
        var tx = $.remote.transaction().payment({
 | 
			
		||||
          from: 'root',
 | 
			
		||||
          to: 'alice',
 | 
			
		||||
          amount: Amount.from_human('1XRP')
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        tx.on('submitted', function() {
 | 
			
		||||
          $.remote.ledger_accept();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        tx.submit();
 | 
			
		||||
 | 
			
		||||
        process.nextTick(function() {
 | 
			
		||||
          $.remote.disconnect();
 | 
			
		||||
 | 
			
		||||
          setTimeout(function() {
 | 
			
		||||
            assert(!$.remote._connected);
 | 
			
		||||
 | 
			
		||||
            tx.once('error', callback);
 | 
			
		||||
            tx.once('success', function() { callback(); });
 | 
			
		||||
 | 
			
		||||
            $.remote.connect();
 | 
			
		||||
          }, 450);
 | 
			
		||||
        });
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function checkPending(callback) {
 | 
			
		||||
        assert.strictEqual($.remote.getAccount('root')._transactionManager._pending.length(), 0, 'Pending transactions persisting');
 | 
			
		||||
        callback();
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        setTimeout(callback, 1000 * 2);
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        testutils.verify_balance($.remote, 'alice', '20001000000', callback);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    async.series(steps, function(err) {
 | 
			
		||||
      assert(!err, self.what + ': ' + err);
 | 
			
		||||
 | 
			
		||||
      assert(self.sent_transactions.length, 'Payment did not send');
 | 
			
		||||
 | 
			
		||||
      assert.strictEqual(self.sent_transactions.length, 1, 'Payment sent more than once');
 | 
			
		||||
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('temporary server disconnection -- reconnect after max ledger wait', function(done) {
 | 
			
		||||
    var self = this;
 | 
			
		||||
 | 
			
		||||
    self.sent_transactions = [ ];
 | 
			
		||||
 | 
			
		||||
    var steps = [
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        self.what = 'Create accounts';
 | 
			
		||||
        testutils.create_accounts($.remote, 'root', '20000.0', [ 'alice' ], callback);
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        $.remote.getAccount('root').on('transaction-outbound', function(tx) {
 | 
			
		||||
          if (tx.transaction.TransactionType === 'Payment' && tx.transaction.Amount === '1000000') {
 | 
			
		||||
            self.sent_transactions.push(tx.transaction);
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        callback();
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        self.what = 'Submit a transaction';
 | 
			
		||||
 | 
			
		||||
        var tx = $.remote.transaction().payment({
 | 
			
		||||
          from: 'root',
 | 
			
		||||
          to: 'alice',
 | 
			
		||||
          amount: Amount.from_human('1XRP')
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        tx.once('submitted', function(m) {
 | 
			
		||||
          assert.strictEqual(m.engine_result, 'tesSUCCESS');
 | 
			
		||||
 | 
			
		||||
          process.nextTick(function() {
 | 
			
		||||
            $.remote.disconnect();
 | 
			
		||||
          });
 | 
			
		||||
 | 
			
		||||
          setTimeout(function() {
 | 
			
		||||
            assert(!$.remote._connected);
 | 
			
		||||
 | 
			
		||||
            tx.once('error', callback);
 | 
			
		||||
            tx.once('success', function() { callback(); });
 | 
			
		||||
 | 
			
		||||
            $.remote.connect();
 | 
			
		||||
          }, 2000);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        tx.submit();
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function checkPending(callback) {
 | 
			
		||||
        assert.strictEqual($.remote.getAccount('root')._transactionManager._pending.length(), 0, 'Pending transactions persisting');
 | 
			
		||||
        callback();
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        setTimeout(callback, 1000 * 2);
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        testutils.verify_balance($.remote, 'alice', '20001000000', callback);
 | 
			
		||||
      }
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    async.series(steps, function(err) {
 | 
			
		||||
      assert(!err, self.what + ': ' + err);
 | 
			
		||||
 | 
			
		||||
      assert(self.sent_transactions.length, 'Payment did not send');
 | 
			
		||||
 | 
			
		||||
      assert.strictEqual(self.sent_transactions.length, 1, 'Payment sent more than once');
 | 
			
		||||
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  // Submit request times out
 | 
			
		||||
  //
 | 
			
		||||
  // Since the transaction ID is generated locally, the
 | 
			
		||||
  // transaction should still validate from the account
 | 
			
		||||
  // transaction stream, even without a response to the
 | 
			
		||||
  // original submit request
 | 
			
		||||
 | 
			
		||||
  test('submission timeout', function(done) {
 | 
			
		||||
    var self = this;
 | 
			
		||||
 | 
			
		||||
    $.remote.local_signing = true;
 | 
			
		||||
 | 
			
		||||
    self.sent_transactions = [ ];
 | 
			
		||||
 | 
			
		||||
    var steps = [
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        self.what = 'Create accounts';
 | 
			
		||||
        testutils.create_accounts($.remote, 'root', '20000.0', [ 'alice' ], callback);
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        $.remote.getAccount('root').on('transaction-outbound', function(tx) {
 | 
			
		||||
          if (tx.transaction.TransactionType === 'Payment' && tx.transaction.Amount === '1000000') {
 | 
			
		||||
            self.sent_transactions.push(tx.transaction);
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
        setTimeout(callback, 100);
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        self.what = 'Submit a transaction whose submit request times out';
 | 
			
		||||
 | 
			
		||||
        var tx = $.remote.transaction().payment({
 | 
			
		||||
          from: 'root',
 | 
			
		||||
          to: 'alice',
 | 
			
		||||
          amount: Amount.from_human('1XRP')
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        $.remote.getAccount('root')._transactionManager._submissionTimeout = 0.00001;
 | 
			
		||||
 | 
			
		||||
        // A response from transaction submission should never
 | 
			
		||||
        // actually be received
 | 
			
		||||
        tx.once('timeout', function() { self.timed_out = true; });
 | 
			
		||||
 | 
			
		||||
        tx.submit(callback);
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        setTimeout(callback, 1000 * 2);
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function checkPending(callback) {
 | 
			
		||||
        assert.strictEqual($.remote.getAccount('root')._transactionManager._pending.length(), 0, 'Pending transactions persisting');
 | 
			
		||||
        callback();
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        testutils.verify_balance($.remote, 'alice', '20001000000', callback);
 | 
			
		||||
      }
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    async.series(steps, function(err) {
 | 
			
		||||
      assert(!err, self.what + ': ' + err);
 | 
			
		||||
 | 
			
		||||
      assert.strictEqual(self.sent_transactions.length, 1, 'Payment sent more than once');
 | 
			
		||||
 | 
			
		||||
      //assert(self.timed_out, 'Transaction submission failed to time out');
 | 
			
		||||
 | 
			
		||||
      assert(self.sent_transactions.length, 'Payment was not sent');
 | 
			
		||||
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  // Subscribing to accounts_proposed will result in ripple-lib
 | 
			
		||||
  // being streamed non-validated (proposed) transactions
 | 
			
		||||
  //
 | 
			
		||||
  // This test ensures that only validated transactions will
 | 
			
		||||
  // trigger a transaction success event
 | 
			
		||||
 | 
			
		||||
  test('subscribe to accounts_proposed', function(done) {
 | 
			
		||||
    var self = this;
 | 
			
		||||
 | 
			
		||||
    var series = [
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        self.what = 'Subscribe to accounts_proposed';
 | 
			
		||||
 | 
			
		||||
        $.remote.requestSubscribe()
 | 
			
		||||
        .addAccountProposed('root')
 | 
			
		||||
        .callback(callback);
 | 
			
		||||
      },
 | 
			
		||||
      function (callback) {
 | 
			
		||||
        self.what = 'Create accounts';
 | 
			
		||||
 | 
			
		||||
        var payment = $.remote.transaction().payment({
 | 
			
		||||
          from: 'root',
 | 
			
		||||
          to: 'alice',
 | 
			
		||||
          amount: Amount.from_human('20000XRP')
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        payment.submit(function(err, m) {
 | 
			
		||||
          assert.ifError(err);
 | 
			
		||||
          assert(m.engine_result, 'tesSUCCESS');
 | 
			
		||||
          assert(m.validated, 'Transaction is finalized with invalidated transaction stream response');
 | 
			
		||||
          done();
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    async.series(series, function(err, m) {
 | 
			
		||||
      assert(!err, self.what + ': ' + err);
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										122
									
								
								test/server.js
									
									
									
									
									
								
							
							
						
						
									
										122
									
								
								test/server.js
									
									
									
									
									
								
							@@ -15,13 +15,13 @@
 | 
			
		||||
// Servers are created in tmp/server/$server
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
var child        = require('child_process');
 | 
			
		||||
var fs           = require('fs');
 | 
			
		||||
var path         = require('path');
 | 
			
		||||
var util         = require('util');
 | 
			
		||||
var child        = require("child_process");
 | 
			
		||||
var fs           = require("fs");
 | 
			
		||||
var path         = require("path");
 | 
			
		||||
var util         = require("util");
 | 
			
		||||
var assert       = require('assert');
 | 
			
		||||
var EventEmitter = require('events').EventEmitter;
 | 
			
		||||
var nodeutils    = require('./nodeutils');
 | 
			
		||||
var nodeutils     = require("./nodeutils");
 | 
			
		||||
 | 
			
		||||
// Create a server object
 | 
			
		||||
function Server(name, config, verbose) {
 | 
			
		||||
@@ -34,7 +34,8 @@ function Server(name, config, verbose) {
 | 
			
		||||
  var nodejs_version = process.version.match(/^v(\d+)+\.(\d+)\.(\d+)$/).slice(1,4);
 | 
			
		||||
  var wanted_version = [ 0, 8, 18 ];
 | 
			
		||||
 | 
			
		||||
  while (wanted_version.length && nodejs_version.length && nodejs_version[0] == wanted_version[0]) {
 | 
			
		||||
  while (wanted_version.length && nodejs_version.length && nodejs_version[0] == wanted_version[0])
 | 
			
		||||
  {
 | 
			
		||||
    nodejs_version.shift();
 | 
			
		||||
    wanted_version.shift();
 | 
			
		||||
  }
 | 
			
		||||
@@ -46,8 +47,8 @@ function Server(name, config, verbose) {
 | 
			
		||||
              : -1;
 | 
			
		||||
 | 
			
		||||
  if (sgn < 0) {
 | 
			
		||||
    console.log('\n*** Node.js version is too low.');
 | 
			
		||||
    throw 'Nodejs version is too low.';
 | 
			
		||||
    console.log("\n*** Node.js version is too low.");
 | 
			
		||||
    throw "Nodejs version is too low.";
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -58,24 +59,23 @@ Server.from_config = function (name, config, verbose) {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Server.prototype.serverPath = function() {
 | 
			
		||||
  return path.resolve('tmp/server', this.name);
 | 
			
		||||
  return path.resolve("tmp/server", this.name);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Server.prototype.configPath = function() {
 | 
			
		||||
  return path.join(this.serverPath(), 'rippled.cfg');
 | 
			
		||||
  return path.join(this.serverPath(), "rippled.cfg");
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Write a server's rippled.cfg.
 | 
			
		||||
Server.prototype._writeConfig = function(done) {
 | 
			
		||||
  var self  = this;
 | 
			
		||||
 | 
			
		||||
  function format(o) {
 | 
			
		||||
    return util.format('[%s]\n%s\n', o, self.config[o]);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  var config = Object.keys(this.config).map(format).join('');
 | 
			
		||||
 | 
			
		||||
  fs.writeFile(this.configPath(), config, 'utf8', done);
 | 
			
		||||
  fs.writeFile(
 | 
			
		||||
    this.configPath(),
 | 
			
		||||
    Object.keys(this.config).map(function(o) {
 | 
			
		||||
        return util.format("[%s]\n%s\n", o, self.config[o]);
 | 
			
		||||
      }).join(""),
 | 
			
		||||
    'utf8', done);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Spawn the server.
 | 
			
		||||
@@ -83,9 +83,9 @@ Server.prototype._serverSpawnSync = function() {
 | 
			
		||||
  var self  = this;
 | 
			
		||||
 | 
			
		||||
  var args  = [
 | 
			
		||||
    '-a',
 | 
			
		||||
    '-v',
 | 
			
		||||
    '--conf=rippled.cfg'
 | 
			
		||||
    "-a",
 | 
			
		||||
    "-v",
 | 
			
		||||
    "--conf=rippled.cfg"
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  var options = {
 | 
			
		||||
@@ -97,56 +97,42 @@ Server.prototype._serverSpawnSync = function() {
 | 
			
		||||
  // Spawn in standalone mode for now.
 | 
			
		||||
  this.child = child.spawn(this.config.rippled_path, args, options);
 | 
			
		||||
 | 
			
		||||
  if (!this.quiet) {
 | 
			
		||||
    console.log('server: start %s: %s --conf=%s',
 | 
			
		||||
  if (!this.quiet)
 | 
			
		||||
    console.log("server: start %s: %s --conf=%s",
 | 
			
		||||
                this.child.pid,
 | 
			
		||||
                this.config.rippled_path,
 | 
			
		||||
                args.join(' '),
 | 
			
		||||
                args.join(" "),
 | 
			
		||||
                this.configPath());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  var stderr = [ ];
 | 
			
		||||
  var ended = false;
 | 
			
		||||
 | 
			
		||||
  this.child.stderr.on('data', function(data) {
 | 
			
		||||
    stderr.push(data);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  this.child.stderr.on('end', function() {
 | 
			
		||||
    ended = true;
 | 
			
		||||
  });
 | 
			
		||||
  
 | 
			
		||||
  
 | 
			
		||||
  var stderr = [];
 | 
			
		||||
  self.child.stderr.on('data', function(buf) { stderr.push(buf); });
 | 
			
		||||
 | 
			
		||||
  // By default, just log exits.
 | 
			
		||||
  this.child.on('exit', function onExit(code, signal) {
 | 
			
		||||
    if (!ended) {
 | 
			
		||||
      return self.child.stderr.once('end', function() {
 | 
			
		||||
        onExit(code, signal);
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!self.quiet) {
 | 
			
		||||
      console.log('server: spawn: server exited code=%s: signal=%s', code, signal);
 | 
			
		||||
    }
 | 
			
		||||
  this.child.on('exit', function(code, signal) {
 | 
			
		||||
    if (!self.quiet) console.log("server: spawn: server exited code=%s: signal=%s", code, signal);
 | 
			
		||||
 | 
			
		||||
    self.emit('exited');
 | 
			
		||||
 | 
			
		||||
    // Dump server logs on an abnormal exit
 | 
			
		||||
    if (self.quiet && !self.stopping) {
 | 
			
		||||
      process.stdout.write('rippled stderr:\n');
 | 
			
		||||
      process.stdout.write(stderr.join(''));
 | 
			
		||||
    if (self.quiet && (!self.stopping)) {
 | 
			
		||||
      process.stderr.write("rippled stderr:\n");
 | 
			
		||||
      for (var i = 0; i < stderr.length; i++) {
 | 
			
		||||
        process.stderr.write(stderr[i]);
 | 
			
		||||
      };
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // If could not exec: code=127, signal=null
 | 
			
		||||
    // If regular exit: code=0, signal=null
 | 
			
		||||
    // Fail the test if the server has not called 'stop'.
 | 
			
		||||
    assert(self.stopping, 'Server died with signal ' + signal);
 | 
			
		||||
    // Fail the test if the server has not called "stop".
 | 
			
		||||
    assert(self.stopping, 'Server died with signal '+signal);
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Prepare server's working directory.
 | 
			
		||||
Server.prototype._makeBase = function (done) {
 | 
			
		||||
  var path = this.serverPath();
 | 
			
		||||
  var self = this;
 | 
			
		||||
  var path  = this.serverPath();
 | 
			
		||||
  var self  = this;
 | 
			
		||||
 | 
			
		||||
  // Reset the server directory, build it if needed.
 | 
			
		||||
  nodeutils.resetPath(path, '0777', function (e) {
 | 
			
		||||
@@ -156,7 +142,7 @@ Server.prototype._makeBase = function (done) {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Server.prototype.verbose = function () {
 | 
			
		||||
  this.quiet = false;
 | 
			
		||||
  this.quiet  = false;
 | 
			
		||||
 | 
			
		||||
  return this;
 | 
			
		||||
};
 | 
			
		||||
@@ -164,14 +150,9 @@ Server.prototype.verbose = function () {
 | 
			
		||||
// Create a standalone server.
 | 
			
		||||
// Prepare the working directory and spawn the server.
 | 
			
		||||
Server.prototype.start = function () {
 | 
			
		||||
  var self = this;
 | 
			
		||||
  var self      = this;
 | 
			
		||||
 | 
			
		||||
  if (!this.quiet) {
 | 
			
		||||
    console.log(
 | 
			
		||||
      'server: start: %s: %s',
 | 
			
		||||
      this.name, JSON.stringify(this.config)
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
  if (!this.quiet) console.log("server: start: %s: %s", this.name, JSON.stringify(this.config));
 | 
			
		||||
 | 
			
		||||
  this._makeBase(function (e) {
 | 
			
		||||
    if (e) throw e;
 | 
			
		||||
@@ -186,25 +167,20 @@ Server.prototype.start = function () {
 | 
			
		||||
Server.prototype.stop = function () {
 | 
			
		||||
  var self  = this;
 | 
			
		||||
 | 
			
		||||
  if (!this.child) {
 | 
			
		||||
    if (!self.quiet) {
 | 
			
		||||
      console.log('server: stop: can\'t stop');
 | 
			
		||||
    }
 | 
			
		||||
    return this;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  self.stopping = true;
 | 
			
		||||
 | 
			
		||||
  if (!this.child) {
 | 
			
		||||
    console.log("server: stop: can't stop");
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Update the on exit to invoke done.
 | 
			
		||||
  function childExited(code, signal) {
 | 
			
		||||
    if (!self.quiet) {
 | 
			
		||||
      console.log('server: stop: server exited');
 | 
			
		||||
    }
 | 
			
		||||
  this.child.on('exit', function (code, signal) {
 | 
			
		||||
    if (!self.quiet) console.log("server: stop: server exited");
 | 
			
		||||
    self.emit('stopped');
 | 
			
		||||
    delete self.child;
 | 
			
		||||
  };
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  this.child.once('exit', childExited);
 | 
			
		||||
  this.child.kill();
 | 
			
		||||
 | 
			
		||||
  return this;
 | 
			
		||||
 
 | 
			
		||||
@@ -42,7 +42,13 @@ function account_dump(remote, account, callback) {
 | 
			
		||||
  request.account_root('root');
 | 
			
		||||
  request.callback(function(err, r) {
 | 
			
		||||
    assert(!err, self.what);
 | 
			
		||||
    callback(err);
 | 
			
		||||
    if (err) {
 | 
			
		||||
      //console.log('error: %s', m);
 | 
			
		||||
      callback(err);
 | 
			
		||||
    } else {
 | 
			
		||||
      //console.log('account_root: %s', JSON.stringify(r, undefined, 2));
 | 
			
		||||
      callback();
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  // get closed ledger hash
 | 
			
		||||
@@ -131,24 +137,11 @@ function build_setup(opts, host) {
 | 
			
		||||
 | 
			
		||||
      function connect_websocket(callback) {
 | 
			
		||||
        self.remote = data.remote = Remote.from_config(host, !!opts.verbose_ws);
 | 
			
		||||
        self.remote.connect(callback);
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function subscribe_account(callback) {
 | 
			
		||||
        var root = self.remote.account('root');
 | 
			
		||||
        self.remote.request_subscribe().accounts(root._account_id).callback(callback);
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function create_ledger_interval(callback) {
 | 
			
		||||
        if (opts.no_auto_ledger_close) {return callback(); };
 | 
			
		||||
 | 
			
		||||
        self.ledger_interval = setInterval(function() {
 | 
			
		||||
          self.remote.ledger_accept();
 | 
			
		||||
        }, 200);  
 | 
			
		||||
 | 
			
		||||
        callback();
 | 
			
		||||
        self.remote.once('ledger_closed', function(ledger) {
 | 
			
		||||
          callback();
 | 
			
		||||
        });
 | 
			
		||||
        self.remote.connect();
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    async.series(series, done);
 | 
			
		||||
@@ -167,19 +160,16 @@ function build_teardown(host) {
 | 
			
		||||
  var host = host || config.server_default;
 | 
			
		||||
 | 
			
		||||
  function teardown(done) {
 | 
			
		||||
    var self = this;
 | 
			
		||||
    var data = this.store[host];
 | 
			
		||||
    var opts = data.opts;
 | 
			
		||||
 | 
			
		||||
    var series = [
 | 
			
		||||
      function clear_ledger_interval(callback) {
 | 
			
		||||
        if (self.ledger_interval != null) {clearInterval(self.ledger_interval)};
 | 
			
		||||
        callback();
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function disconnect_websocket(callback) {
 | 
			
		||||
        data.remote.once('disconnected', callback)
 | 
			
		||||
        data.remote.disconnect();
 | 
			
		||||
        data.remote.once('error', function (m) {
 | 
			
		||||
          //console.log('server error: ', m);
 | 
			
		||||
        })
 | 
			
		||||
        data.remote.connect(false);
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      function stop_server(callback) {
 | 
			
		||||
@@ -200,25 +190,35 @@ function build_teardown(host) {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function create_accounts(remote, src, amount, accounts, callback) {
 | 
			
		||||
  assert.strictEqual(arguments.length, 5);
 | 
			
		||||
  assert(arguments.length === 5);
 | 
			
		||||
 | 
			
		||||
  remote.set_account_seq(src, 1);
 | 
			
		||||
 | 
			
		||||
  async.forEach(accounts, function (account, nextAccount) {
 | 
			
		||||
  async.forEach(accounts, function (account, callback) {
 | 
			
		||||
    // Cache the seq as 1.
 | 
			
		||||
    // Otherwise, when other operations attempt to opperate async against the account they may get confused.
 | 
			
		||||
 | 
			
		||||
    remote.set_account_seq(account, 1);
 | 
			
		||||
 | 
			
		||||
    var tx = remote.transaction();
 | 
			
		||||
    tx.payment(src, account, amount);
 | 
			
		||||
    tx.submit(nextAccount);
 | 
			
		||||
 | 
			
		||||
    tx.payment(src, account, amount);
 | 
			
		||||
 | 
			
		||||
    tx.once('proposed', function (m) {
 | 
			
		||||
      //console.log('proposed: %s', JSON.stringify(m));
 | 
			
		||||
      callback(m.engine_result === 'tesSUCCESS' ? null : new Error());
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    tx.once('error', function (m) {
 | 
			
		||||
      //console.log('error: %s', JSON.stringify(m));
 | 
			
		||||
      callback(m);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    tx.submit();
 | 
			
		||||
  }, callback);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function credit_limit(remote, src, amount, callback) {
 | 
			
		||||
  assert.strictEqual(arguments.length, 4);
 | 
			
		||||
  assert(arguments.length === 4);
 | 
			
		||||
 | 
			
		||||
  var _m = amount.match(/^(\d+\/...\/[^\:]+)(?::(\d+)(?:,(\d+))?)?$/);
 | 
			
		||||
 | 
			
		||||
@@ -232,24 +232,25 @@ function credit_limit(remote, src, amount, callback) {
 | 
			
		||||
  var quality_in    = _m[2];
 | 
			
		||||
  var quality_out   = _m[3];
 | 
			
		||||
 | 
			
		||||
  var tx = remote.transaction();
 | 
			
		||||
  var tx = remote.transaction()
 | 
			
		||||
 | 
			
		||||
  tx.ripple_line_set(src, account_limit, quality_in, quality_out);
 | 
			
		||||
  tx.ripple_line_set(src, account_limit, quality_in, quality_out)
 | 
			
		||||
 | 
			
		||||
  tx.submit(function(err,  m) {
 | 
			
		||||
    //console.log('proposed: %s', JSON.stringify(m));
 | 
			
		||||
    if (err) {
 | 
			
		||||
      callback(err);
 | 
			
		||||
    } else if (m.engine_result === 'tesSUCCESS') {
 | 
			
		||||
      callback();
 | 
			
		||||
    } else {
 | 
			
		||||
      callback(m);
 | 
			
		||||
    }
 | 
			
		||||
  tx.once('proposed', function (m) {
 | 
			
		||||
    // console.log('proposed: %s', JSON.stringify(m));
 | 
			
		||||
    callback(m.engine_result === 'tesSUCCESS' ? null : new Error());
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  tx.once('error', function (m) {
 | 
			
		||||
    // console.log('error: %s', JSON.stringify(m));
 | 
			
		||||
    callback(m);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  tx.submit();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function verify_limit(remote, src, amount, callback) {
 | 
			
		||||
  assert.strictEqual(arguments.length, 4);
 | 
			
		||||
  assert(arguments.length === 4);
 | 
			
		||||
 | 
			
		||||
  var _m = amount.match(/^(\d+\/...\/[^\:]+)(?::(\d+)(?:,(\d+))?)?$/);
 | 
			
		||||
 | 
			
		||||
@@ -279,13 +280,13 @@ function verify_limit(remote, src, amount, callback) {
 | 
			
		||||
      assert(m.account_limit.equals(limit));
 | 
			
		||||
      assert(isNaN(quality_in) || m.account_quality_in === quality_in);
 | 
			
		||||
      assert(isNaN(quality_out) || m.account_quality_out === quality_out);
 | 
			
		||||
      callback();
 | 
			
		||||
      callback(null);
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function credit_limits(remote, balances, callback) {
 | 
			
		||||
  assert.strictEqual(arguments.length, 3);
 | 
			
		||||
  assert(arguments.length === 3);
 | 
			
		||||
 | 
			
		||||
  var limits = [ ];
 | 
			
		||||
 | 
			
		||||
@@ -300,7 +301,7 @@ function credit_limits(remote, balances, callback) {
 | 
			
		||||
 | 
			
		||||
  function iterator(limit, callback) {
 | 
			
		||||
    credit_limit(remote, limit.source, limit.amount, callback);
 | 
			
		||||
  };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async.some(limits, iterator, callback);
 | 
			
		||||
};
 | 
			
		||||
@@ -313,26 +314,26 @@ function ledger_close(remote, callback) {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function payment(remote, src, dst, amount, callback) {
 | 
			
		||||
  assert.strictEqual(arguments.length, 5);
 | 
			
		||||
  assert(arguments.length === 5);
 | 
			
		||||
 | 
			
		||||
  var tx = remote.transaction();
 | 
			
		||||
 | 
			
		||||
  tx.payment(src, dst, amount);
 | 
			
		||||
 | 
			
		||||
  tx.submit(function(err, m) {
 | 
			
		||||
  tx.once('proposed', function (m) {
 | 
			
		||||
    // console.log('proposed: %s', JSON.stringify(m));
 | 
			
		||||
    if (err) {
 | 
			
		||||
      callback(err);
 | 
			
		||||
    } else if (m.engine_result === 'tesSUCCESS') {
 | 
			
		||||
      callback();
 | 
			
		||||
    } else {
 | 
			
		||||
      callback(m);
 | 
			
		||||
    }
 | 
			
		||||
    callback(m.engine_result === 'tesSUCCESS' ? null : new Error());
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  tx.once('error', function (m) {
 | 
			
		||||
    // console.log('error: %s', JSON.stringify(m));
 | 
			
		||||
    callback(m);
 | 
			
		||||
  });
 | 
			
		||||
  tx.submit();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function payments(remote, balances, callback) {
 | 
			
		||||
  assert.strictEqual(arguments.length, 3);
 | 
			
		||||
  assert(arguments.length === 3);
 | 
			
		||||
 | 
			
		||||
  var sends = [ ];
 | 
			
		||||
 | 
			
		||||
@@ -348,7 +349,7 @@ function payments(remote, balances, callback) {
 | 
			
		||||
 | 
			
		||||
  function iterator(send, callback) {
 | 
			
		||||
    payment(remote, send.source, send.destination, send.amount, callback);
 | 
			
		||||
  };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async.some(sends, iterator, callback);
 | 
			
		||||
};
 | 
			
		||||
@@ -359,39 +360,63 @@ function transfer_rate(remote, src, billionths, callback) {
 | 
			
		||||
  var tx = remote.transaction();
 | 
			
		||||
  tx.account_set(src);
 | 
			
		||||
  tx.transfer_rate(billionths);
 | 
			
		||||
  tx.submit(callback);
 | 
			
		||||
 | 
			
		||||
  tx.once('proposed', function (m) {
 | 
			
		||||
    // console.log('proposed: %s', JSON.stringify(m));
 | 
			
		||||
    callback(m.engine_result === 'tesSUCCESS' ? null : new Error());
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  tx.once('error', function (m) {
 | 
			
		||||
    // console.log('error: %s', JSON.stringify(m));
 | 
			
		||||
    callback(m);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  tx.submit();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function verify_balance(remote, src, amount_json, callback) {
 | 
			
		||||
  assert.strictEqual(arguments.length, 4);
 | 
			
		||||
  assert(arguments.length === 4);
 | 
			
		||||
 | 
			
		||||
  var amount_req  = Amount.from_json(amount_json);
 | 
			
		||||
 | 
			
		||||
  if (amount_req.is_native()) {
 | 
			
		||||
    remote.request_account_balance(src, 'CURRENT', function(err, amount_act) {
 | 
			
		||||
      assert.ifError(err);
 | 
			
		||||
      assert.strictEqual(amount_act.to_json(), amount_req.to_json());
 | 
			
		||||
      callback();
 | 
			
		||||
      if (err) {
 | 
			
		||||
        return callback(err);
 | 
			
		||||
      }
 | 
			
		||||
      var valid_balance = amount_act.equals(amount_req, true);
 | 
			
		||||
      if (!valid_balance) {
 | 
			
		||||
        //console.log('verify_balance: failed: %s / %s',
 | 
			
		||||
        //amount_act.to_text_full(),
 | 
			
		||||
        //amount_req.to_text_full());
 | 
			
		||||
      }
 | 
			
		||||
      callback(valid_balance ? null : new Error());
 | 
			
		||||
    });
 | 
			
		||||
  } else {
 | 
			
		||||
    var issuer = amount_req.issuer().to_json();
 | 
			
		||||
    var currency = amount_req.currency().to_json();
 | 
			
		||||
    remote.request_ripple_balance(src, issuer, currency, 'CURRENT', function(err, m) {
 | 
			
		||||
      if (err) return callback(err);
 | 
			
		||||
 | 
			
		||||
      if (err) {
 | 
			
		||||
        return callback(err);
 | 
			
		||||
      }
 | 
			
		||||
      // console.log('BALANCE: %s', JSON.stringify(m));
 | 
			
		||||
      // console.log('account_balance: %s', m.account_balance.to_text_full());
 | 
			
		||||
      // console.log('account_limit: %s', m.account_limit.to_text_full());
 | 
			
		||||
      // console.log('issuer_balance: %s', m.issuer_balance.to_text_full());
 | 
			
		||||
      // console.log('issuer_limit: %s', m.issuer_limit.to_text_full());
 | 
			
		||||
      var account_balance = Amount.from_json(m.account_balance);
 | 
			
		||||
 | 
			
		||||
      var valid_balance = account_balance.equals(amount_req, true);
 | 
			
		||||
 | 
			
		||||
      if (valid_balance) {
 | 
			
		||||
        callback();
 | 
			
		||||
      } else {
 | 
			
		||||
        callback(new Error('Invalid balance: ' + amount_req.to_text() + '/' + Amount.from_json(account_balance).to_text()));
 | 
			
		||||
      if (!valid_balance) {
 | 
			
		||||
        //console.log('verify_balance: failed: %s vs %s / %s: %s',
 | 
			
		||||
        //src,
 | 
			
		||||
        //account_balance.to_text_full(),
 | 
			
		||||
        //amount_req.to_text_full(),
 | 
			
		||||
        //account_balance.not_equals_why(amount_req, true));
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      callback(valid_balance ? null : new Error());
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
@@ -407,9 +432,9 @@ function verify_balances(remote, balances, callback) {
 | 
			
		||||
 | 
			
		||||
  function iterator(test, callback) {
 | 
			
		||||
    verify_balance(remote, test.source, test.amount, callback)
 | 
			
		||||
  };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async.eachSeries(tests, iterator, callback);
 | 
			
		||||
  async.every(tests, iterator, callback);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// --> owner: account
 | 
			
		||||
@@ -417,7 +442,7 @@ function verify_balances(remote, balances, callback) {
 | 
			
		||||
// --> taker_gets: json amount
 | 
			
		||||
// --> taker_pays: json amount
 | 
			
		||||
function verify_offer(remote, owner, seq, taker_pays, taker_gets, callback) {
 | 
			
		||||
  assert.strictEqual(arguments.length, 6);
 | 
			
		||||
  assert(arguments.length === 6);
 | 
			
		||||
 | 
			
		||||
  var request = remote.request_ledger_entry('offer')
 | 
			
		||||
  request.offer_id(owner, seq)
 | 
			
		||||
@@ -428,41 +453,43 @@ function verify_offer(remote, owner, seq, taker_pays, taker_gets, callback) {
 | 
			
		||||
 | 
			
		||||
    if (wrong) {
 | 
			
		||||
      //console.log('verify_offer: failed: %s', JSON.stringify(m));
 | 
			
		||||
      callback(err);
 | 
			
		||||
    } else {
 | 
			
		||||
      callback();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    callback(wrong ? (err || new Error()) : null);
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function verify_offer_not_found(remote, owner, seq, callback) {
 | 
			
		||||
  assert.strictEqual(arguments.length, 4);
 | 
			
		||||
  assert(arguments.length === 4);
 | 
			
		||||
 | 
			
		||||
  var request = remote.request_ledger_entry('offer');
 | 
			
		||||
 | 
			
		||||
  request.offer_id(owner, seq);
 | 
			
		||||
  request.callback(function(err, m) {
 | 
			
		||||
    if (err && err.error === 'remoteError' && err.remote.error === 'entryNotFound') {
 | 
			
		||||
      callback();
 | 
			
		||||
 | 
			
		||||
  request.once('success', function (m) {
 | 
			
		||||
    //console.log('verify_offer_not_found: found offer: %s', JSON.stringify(m));
 | 
			
		||||
    callback(new Error('entryFound'));
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  request.once('error', function (m) {
 | 
			
		||||
    // console.log('verify_offer_not_found: success: %s', JSON.stringify(m));
 | 
			
		||||
    var is_not_found = m.error === 'remoteError' && m.remote.error === 'entryNotFound';
 | 
			
		||||
    if (is_not_found) {
 | 
			
		||||
      callback(null);
 | 
			
		||||
    } else {
 | 
			
		||||
      callback(new Error('Expected remoteError entryNotFound: ' + m));
 | 
			
		||||
      callback(new Error());
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  request.request();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function verify_owner_count(remote, account, count, callback) {
 | 
			
		||||
  assert.strictEqual(arguments.length, 4);
 | 
			
		||||
 | 
			
		||||
  assert(arguments.length === 4);
 | 
			
		||||
  var options = { account: account, ledger: 'CURRENT' };
 | 
			
		||||
 | 
			
		||||
  remote.request_owner_count(options, function(err, owner_count) {
 | 
			
		||||
    //console.log('owner_count: %s/%d', owner_count, value);
 | 
			
		||||
    if (err) {
 | 
			
		||||
      callback(err);
 | 
			
		||||
    } else if (owner_count !== count) {
 | 
			
		||||
      callback(new Error('Owner count mismatch: ' + owner_count + '/' + count));
 | 
			
		||||
    } else {
 | 
			
		||||
      callback();
 | 
			
		||||
    }
 | 
			
		||||
    callback(owner_count === count ? null : new Error());
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -473,15 +500,9 @@ function verify_owner_counts(remote, counts, callback) {
 | 
			
		||||
 | 
			
		||||
  function iterator(test, callback) {
 | 
			
		||||
    verify_owner_count(remote, test.account, test.count, callback)
 | 
			
		||||
  };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async.eachSeries(tests, iterator, function(err) {
 | 
			
		||||
    if (err) {
 | 
			
		||||
      callback();
 | 
			
		||||
    } else {
 | 
			
		||||
      callback(new Error('Owner counts mismatch'));
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
  async.every(tests, iterator, callback);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
exports.account_dump            = account_dump;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user