From 6c5f88aa250a8f24b4ca0fabf3e19e1135519e16 Mon Sep 17 00:00:00 2001 From: wltsmrz Date: Wed, 29 Jan 2014 14:22:19 -0800 Subject: [PATCH] Update ripple-lib integration tests --- package.json | 4 +- test/mocha.opts | 2 +- test/no-ripple-test.js | 314 ++++++++++ test/robust-transaction-test.js | 444 +++++++++++++++ test/send-test.js | 979 +++++++++++++++++--------------- test/server.js | 120 ++-- test/testutils.js | 210 +++---- 7 files changed, 1440 insertions(+), 633 deletions(-) create mode 100644 test/no-ripple-test.js create mode 100644 test/robust-transaction-test.js diff --git a/package.json b/package.json index a70d16190..8b5169e98 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ }, "dependencies": { - "ripple-lib": "0.7.25", + "ripple-lib": "0.7.31", "async": "~0.2.9", "extend": "~1.2.0", "simple-jsonrpc": "~0.0.2", @@ -31,4 +31,4 @@ }, "readmeFilename": "README.md" -} \ No newline at end of file +} diff --git a/test/mocha.opts b/test/mocha.opts index 77a7a3544..6bc3ae6e9 100644 --- a/test/mocha.opts +++ b/test/mocha.opts @@ -2,4 +2,4 @@ --compilers coffee:coffee-script --ui tdd --timeout 10000 ---slow 600 \ No newline at end of file +--slow 600 diff --git a/test/no-ripple-test.js b/test/no-ripple-test.js new file mode 100644 index 000000000..c8ec0df4b --- /dev/null +++ b/test/no-ripple-test.js @@ -0,0 +1,314 @@ +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(); + }); + }); +}); diff --git a/test/robust-transaction-test.js b/test/robust-transaction-test.js new file mode 100644 index 000000000..1b0818b58 --- /dev/null +++ b/test/robust-transaction-test.js @@ -0,0 +1,444 @@ +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(); + }); + }); +}); diff --git a/test/send-test.js b/test/send-test.js index 0ba6d6d7a..64320e94c 100644 --- a/test/send-test.js +++ b/test/send-test.js @@ -1,9 +1,9 @@ -var async = require("async"); +var async = require('async'); var assert = require('assert'); -var Amount = require("ripple-lib").Amount; -var Remote = require("ripple-lib").Remote; -var Server = require("./server").Server; -var testutils = require("./testutils"); +var Amount = require('ripple-lib').Amount; +var Remote = require('ripple-lib').Remote; +var Server = require('./server').Server; +var testutils = require('./testutils'); var config = testutils.init_config(); suite('Sending', function() { @@ -17,22 +17,21 @@ suite('Sending', function() { testutils.build_teardown().call($, done); }); - test("send XRP to non-existent account with insufficent fee", function (done) { + test('send XRP to non-existent account with insufficent fee', function (done) { var self = this; var ledgers = 20; var got_proposed; $.remote.transaction() - .payment('root', 'alice', "1") + .payment('root', 'alice', '1') .once('submitted', function (m) { // Transaction got an error. - // console.log("proposed: %s", JSON.stringify(m)); + // console.log('proposed: %s', JSON.stringify(m)); assert.strictEqual(m.engine_result, 'tecNO_DST_INSUF_XRP'); got_proposed = true; - $.remote.ledger_accept(); // Move it along. }) .once('final', function (m) { - // console.log("final: %s", JSON.stringify(m, undefined, 2)); + // console.log('final: %s', JSON.stringify(m, undefined, 2)); assert.strictEqual(m.engine_result, 'tecNO_DST_INSUF_XRP'); done(); }) @@ -40,36 +39,37 @@ suite('Sending', function() { }); // Also test transaction becomes lost after tecNO_DST. - test("credit_limit to non-existent account = tecNO_DST", function (done) { + test('credit_limit to non-existent account = tecNO_DST', function (done) { $.remote.transaction() - .ripple_line_set("root", "100/USD/alice") + .ripple_line_set('root', '100/USD/alice') .once('submitted', function (m) { - //console.log("proposed: %s", JSON.stringify(m)); + //console.log('proposed: %s', JSON.stringify(m)); assert.strictEqual(m.engine_result, 'tecNO_DST'); done(); }) .submit(); }); - test("credit_limit", function (done) { + test('credit_limit', function (done) { var self = this; + $.remote.local_signing = true; + var steps = [ function (callback) { - self.what = "Create accounts."; - testutils.create_accounts($.remote, "root", "10000.0", ["alice", "bob", "mtgox"], callback); + self.what = 'Create accounts.'; + testutils.create_accounts($.remote, 'root', '10000.0', ['alice', 'bob', 'mtgox'], callback); }, function (callback) { - self.what = "Check a non-existent credit limit."; + self.what = 'Check a non-existent credit limit.'; - $.remote.request_ripple_balance("alice", "mtgox", "USD", 'CURRENT') - .on('ripple_state', function (m) { - callback(new Error(m)); + $.remote.request_ripple_balance('alice', 'mtgox', 'USD', 'CURRENT') + .once('ripple_state', function (m) { + callback(m); }) - .on('error', function(m) { - // console.log("error: %s", JSON.stringify(m)); - + .once('error', function(m) { + // console.log('error: %s', JSON.stringify(m)); assert.strictEqual('remoteError', m.error); assert.strictEqual('entryNotFound', m.remote.error); callback(); @@ -78,22 +78,22 @@ suite('Sending', function() { }, function (callback) { - self.what = "Create a credit limit."; - testutils.credit_limit($.remote, "alice", "800/USD/mtgox", callback); + self.what = 'Create a credit limit.'; + testutils.credit_limit($.remote, 'alice', '800/USD/mtgox', callback); }, function (callback) { - $.remote.request_ripple_balance("alice", "mtgox", "USD", 'CURRENT') - .on('ripple_state', function (m) { - // 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("peer_balance: %s", m.peer_balance.to_text_full()); - // console.log("peer_limit: %s", m.peer_limit.to_text_full()); - assert(m.account_balance.equals("0/USD/alice")); - assert(m.account_limit.equals("800/USD/mtgox")); - assert(m.peer_balance.equals("0/USD/mtgox")); - assert(m.peer_limit.equals("0/USD/alice")); + $.remote.request_ripple_balance('alice', 'mtgox', 'USD', 'CURRENT') + .once('ripple_state', function (m) { + // 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('peer_balance: %s', m.peer_balance.to_text_full()); + // console.log('peer_limit: %s', m.peer_limit.to_text_full()); + assert(m.account_balance.equals('0/USD/alice')); + assert(m.account_limit.equals('800/USD/mtgox')); + assert(m.peer_balance.equals('0/USD/mtgox')); + assert(m.peer_limit.equals('0/USD/alice')); callback(); }) @@ -101,17 +101,17 @@ suite('Sending', function() { }, function (callback) { - self.what = "Modify a credit limit."; - testutils.credit_limit($.remote, "alice", "700/USD/mtgox", callback); + self.what = 'Modify a credit limit.'; + testutils.credit_limit($.remote, 'alice', '700/USD/mtgox', callback); }, function (callback) { - $.remote.request_ripple_balance("alice", "mtgox", "USD", 'CURRENT') - .on('ripple_state', function (m) { - assert(m.account_balance.equals("0/USD/alice")); - assert(m.account_limit.equals("700/USD/mtgox")); - assert(m.peer_balance.equals("0/USD/mtgox")); - assert(m.peer_limit.equals("0/USD/alice")); + $.remote.request_ripple_balance('alice', 'mtgox', 'USD', 'CURRENT') + .once('ripple_state', function (m) { + assert(m.account_balance.equals('0/USD/alice')); + assert(m.account_limit.equals('700/USD/mtgox')); + assert(m.peer_balance.equals('0/USD/mtgox')); + assert(m.peer_limit.equals('0/USD/alice')); callback(); }) @@ -120,7 +120,7 @@ suite('Sending', function() { // Set negative limit. function (callback) { $.remote.transaction() - .ripple_line_set("alice", "-1/USD/mtgox") + .ripple_line_set('alice', '-1/USD/mtgox') .once('submitted', function (m) { assert.strictEqual('temBAD_LIMIT', m.engine_result); callback(); @@ -129,11 +129,11 @@ suite('Sending', function() { }, // function (callback) { - // self.what = "Display ledger"; + // self.what = 'Display ledger'; // // $.remote.request_ledger('current', true) // .on('success', function (m) { - // console.log("Ledger: %s", JSON.stringify(m, undefined, 2)); + // console.log('Ledger: %s', JSON.stringify(m, undefined, 2)); // // callback(); // }) @@ -141,24 +141,25 @@ suite('Sending', function() { // }, function (callback) { - self.what = "Zero a credit limit."; - testutils.credit_limit($.remote, "alice", "0/USD/mtgox", callback); + self.what = 'Zero a credit limit.'; + //$.remote.trace = true; + testutils.credit_limit($.remote, 'alice', '0/USD/mtgox', callback); }, function (callback) { - self.what = "Make sure line is deleted."; + self.what = 'Make sure line is deleted.'; - $.remote.request_ripple_balance("alice", "mtgox", "USD", 'CURRENT') - .on('ripple_state', function (m) { + $.remote.request_ripple_balance('alice', 'mtgox', 'USD', 'CURRENT') + .once('ripple_state', function (m) { // Used to keep lines. - // assert(m.account_balance.equals("0/USD/alice")); - // assert(m.account_limit.equals("0/USD/alice")); - // assert(m.peer_balance.equals("0/USD/mtgox")); - // assert(m.peer_limit.equals("0/USD/mtgox")); - callback(new Error(m)); + // assert(m.account_balance.equals('0/USD/alice')); + // assert(m.account_limit.equals('0/USD/alice')); + // assert(m.peer_balance.equals('0/USD/mtgox')); + // assert(m.peer_limit.equals('0/USD/mtgox')); + callback(m); }) - .on('error', function (m) { - // console.log("error: %s", JSON.stringify(m)); + .once('error', function (m) { + // console.log('error: %s', JSON.stringify(m)); assert.strictEqual('remoteError', m.error); assert.strictEqual('entryNotFound', m.remote.error); @@ -168,26 +169,26 @@ suite('Sending', function() { }, // TODO Check in both owner books. function (callback) { - self.what = "Set another limit."; - testutils.credit_limit($.remote, "alice", "600/USD/bob", callback); + self.what = 'Set another limit.'; + testutils.credit_limit($.remote, 'alice', '600/USD/bob', callback); }, function (callback) { - self.what = "Set limit on other side."; - testutils.credit_limit($.remote, "bob", "500/USD/alice", callback); + self.what = 'Set limit on other side.'; + testutils.credit_limit($.remote, 'bob', '500/USD/alice', callback); }, function (callback) { - self.what = "Check ripple_line's state from alice's pov."; + self.what = 'Check ripple_line\'s state from alice\'s pov.'; - $.remote.request_ripple_balance("alice", "bob", "USD", 'CURRENT') - .on('ripple_state', function (m) { - // console.log("proposed: %s", JSON.stringify(m)); + $.remote.request_ripple_balance('alice', 'bob', 'USD', 'CURRENT') + .once('ripple_state', function (m) { + // console.log('proposed: %s', JSON.stringify(m)); - assert(m.account_balance.equals("0/USD/alice")); - assert(m.account_limit.equals("600/USD/bob")); - assert(m.peer_balance.equals("0/USD/bob")); - assert(m.peer_limit.equals("500/USD/alice")); + assert(m.account_balance.equals('0/USD/alice')); + assert(m.account_limit.equals('600/USD/bob')); + assert(m.peer_balance.equals('0/USD/bob')); + assert(m.peer_limit.equals('500/USD/alice')); callback(); }) @@ -195,14 +196,14 @@ suite('Sending', function() { }, function (callback) { - self.what = "Check ripple_line's state from bob's pov."; + self.what = 'Check ripple_line\'s state from bob\'s pov.'; - $.remote.request_ripple_balance("bob", "alice", "USD", 'CURRENT') - .on('ripple_state', function (m) { - assert(m.account_balance.equals("0/USD/bob")); - assert(m.account_limit.equals("500/USD/alice")); - assert(m.peer_balance.equals("0/USD/alice")); - assert(m.peer_limit.equals("600/USD/bob")); + $.remote.request_ripple_balance('bob', 'alice', 'USD', 'CURRENT') + .once('ripple_state', function (m) { + assert(m.account_balance.equals('0/USD/bob')); + assert(m.account_limit.equals('500/USD/alice')); + assert(m.peer_balance.equals('0/USD/alice')); + assert(m.peer_limit.equals('600/USD/bob')); callback(); }) @@ -210,8 +211,8 @@ suite('Sending', function() { } ] - async.waterfall(steps, function(error) { - assert(!error, self.what); + async.series(steps, function(err) { + assert(!err, self.what + ': ' + err); done(); }); }); @@ -231,46 +232,41 @@ suite('Sending future', function() { test('direct ripple', function(done) { var self = this; - // $.remote.set_trace(); - var steps = [ function (callback) { - self.what = "Create accounts."; - testutils.create_accounts($.remote, "root", "10000.0", ["alice", "bob"], callback); + self.what = 'Create accounts.'; + testutils.create_accounts($.remote, 'root', '10000.0', ['alice', 'bob'], callback); }, function (callback) { - self.what = "Set alice's limit."; - testutils.credit_limit($.remote, "alice", "600/USD/bob", callback); + self.what = 'Set alice\'s limit.'; + testutils.credit_limit($.remote, 'alice', '600/USD/bob', callback); }, function (callback) { - self.what = "Set bob's limit."; - testutils.credit_limit($.remote, "bob", "700/USD/alice", callback); + self.what = 'Set bob\'s limit.'; + testutils.credit_limit($.remote, 'bob', '700/USD/alice', callback); }, function (callback) { - self.what = "Set alice send bob partial with alice as issuer."; + self.what = 'Set alice send bob partial with alice as issuer.'; $.remote.transaction() - .payment('alice', 'bob', "24/USD/alice") - .once('submitted', function (m) { - // console.log("proposed: %s", JSON.stringify(m)); - callback(m.engine_result !== 'tesSUCCESS'); - }) + .payment('alice', 'bob', '24/USD/alice') .once('final', function (m) { - assert(m.engine_result !== 'tesSUCCESS'); + assert.strictEqual(m.engine_result, 'tesSUCCESS'); + callback(); }) .submit(); }, function (callback) { - self.what = "Verify balance."; + self.what = 'Verify balance.'; - $.remote.request_ripple_balance("alice", "bob", "USD", 'CURRENT') + $.remote.request_ripple_balance('alice', 'bob', 'USD', 'CURRENT') .once('ripple_state', function (m) { - assert(m.account_balance.equals("-24/USD/alice")); - assert(m.peer_balance.equals("24/USD/bob")); + assert(m.account_balance.equals('-24/USD/alice')); + assert(m.peer_balance.equals('24/USD/bob')); callback(); }) @@ -278,27 +274,24 @@ suite('Sending future', function() { }, function (callback) { - self.what = "Set alice send bob more with bob as issuer."; + self.what = 'Set alice send bob more with bob as issuer.'; $.remote.transaction() - .payment('alice', 'bob', "33/USD/bob") - .once('submitted', function (m) { - // console.log("proposed: %s", JSON.stringify(m)); - callback(m.engine_result !== 'tesSUCCESS'); - }) + .payment('alice', 'bob', '33/USD/bob') .once('final', function (m) { - assert(m.engine_result !== 'tesSUCCESS'); + assert.strictEqual(m.engine_result, 'tesSUCCESS'); + callback(); }) .submit(); }, function (callback) { - self.what = "Verify balance from bob's pov."; + self.what = 'Verify balance from bob\'s pov.'; - $.remote.request_ripple_balance("bob", "alice", "USD", 'CURRENT') + $.remote.request_ripple_balance('bob', 'alice', 'USD', 'CURRENT') .once('ripple_state', function (m) { - assert(m.account_balance.equals("57/USD/bob")); - assert(m.peer_balance.equals("-57/USD/alice")); + assert(m.account_balance.equals('57/USD/bob')); + assert(m.peer_balance.equals('-57/USD/alice')); callback(); }) @@ -306,26 +299,23 @@ suite('Sending future', function() { }, function (callback) { - self.what = "Bob send back more than sent."; + self.what = 'Bob send back more than sent.'; $.remote.transaction() - .payment('bob', 'alice', "90/USD/bob") - .once('submitted', function (m) { - // console.log("proposed: %s", JSON.stringify(m)); - callback(m.engine_result !== 'tesSUCCESS'); - }) + .payment('bob', 'alice', '90/USD/bob') .once('final', function (m) { - assert(m.engine_result !== 'tesSUCCESS'); + assert.strictEqual(m.engine_result, 'tesSUCCESS'); + callback(); }) .submit(); }, function (callback) { - self.what = "Verify balance from alice's pov: 1"; + self.what = 'Verify balance from alice\'s pov: 1'; - $.remote.request_ripple_balance("alice", "bob", "USD", 'CURRENT') + $.remote.request_ripple_balance('alice', 'bob', 'USD', 'CURRENT') .once('ripple_state', function (m) { - assert(m.account_balance.equals("33/USD/alice")); + assert(m.account_balance.equals('33/USD/alice')); callback(); }) @@ -333,54 +323,46 @@ suite('Sending future', function() { }, function (callback) { - self.what = "Alice send to limit."; + self.what = 'Alice send to limit.'; $.remote.transaction() - .payment('alice', 'bob', "733/USD/bob") - .once('submitted', function (m) { - // console.log("submitted: %s", JSON.stringify(m)); - callback(m.engine_result !== 'tesSUCCESS'); - }) + .payment('alice', 'bob', '733/USD/bob') .once('final', function (m) { - assert(m.engine_result !== 'tesSUCCESS'); + assert.strictEqual(m.engine_result, 'tesSUCCESS'); + callback(); }) .submit(); }, function (callback) { - self.what = "Verify balance from alice's pov: 2"; + self.what = 'Verify balance from alice\'s pov: 2'; - $.remote.request_ripple_balance("alice", "bob", "USD", 'CURRENT') + $.remote.request_ripple_balance('alice', 'bob', 'USD', 'CURRENT') .once('ripple_state', function (m) { - assert(m.account_balance.equals("-700/USD/alice")); - + assert(m.account_balance.equals('-700/USD/alice')); callback(); }) .request(); }, function (callback) { - self.what = "Bob send to limit."; + self.what = 'Bob send to limit.'; $.remote.transaction() - .payment('bob', 'alice', "1300/USD/bob") - .once('submitted', function (m) { - // console.log("submitted: %s", JSON.stringify(m)); - callback(m.engine_result !== 'tesSUCCESS'); - }) + .payment('bob', 'alice', '1300/USD/bob') .once('final', function (m) { - assert(m.engine_result !== 'tesSUCCESS'); + assert.strictEqual(m.engine_result, 'tesSUCCESS'); + callback(); }) .submit(); }, function (callback) { - self.what = "Verify balance from alice's pov: 3"; + self.what = 'Verify balance from alice\'s pov: 3'; - $.remote.request_ripple_balance("alice", "bob", "USD", 'CURRENT') + $.remote.request_ripple_balance('alice', 'bob', 'USD', 'CURRENT') .once('ripple_state', function (m) { - assert(m.account_balance.equals("600/USD/alice")); - + assert(m.account_balance.equals('600/USD/alice')); callback(); }) .request(); @@ -388,24 +370,24 @@ suite('Sending future', function() { function (callback) { // If this gets applied out of order, it could stop the big payment. - self.what = "Bob send past limit."; + self.what = 'Bob send past limit.'; $.remote.transaction() - .payment('bob', 'alice', "1/USD/bob") + .payment('bob', 'alice', '1/USD/bob') .once('submitted', function (m) { - // console.log("submitted: %s", JSON.stringify(m)); - callback(m.engine_result !== 'tecPATH_DRY'); + // console.log('submitted: %s', JSON.stringify(m)); + assert.strictEqual(m.engine_result, 'tecPATH_DRY'); + callback(); }) .submit(); }, function (callback) { - self.what = "Verify balance from alice's pov: 4"; + self.what = 'Verify balance from alice\'s pov: 4'; - $.remote.request_ripple_balance("alice", "bob", "USD", 'CURRENT') + $.remote.request_ripple_balance('alice', 'bob', 'USD', 'CURRENT') .once('ripple_state', function (m) { - assert(m.account_balance.equals("600/USD/alice")); - + assert(m.account_balance.equals('600/USD/alice')); callback(); }) .request(); @@ -413,26 +395,25 @@ suite('Sending future', function() { // function (callback) { // // Make sure all is good after canonical ordering. - // self.what = "Close the ledger and check balance."; + // self.what = 'Close the ledger and check balance.'; // // $.remote // .once('ledger_closed', function (message) { - // // console.log("LEDGER_CLOSED: A: %d: %s", ledger_closed_index, ledger_closed); + // // console.log('LEDGER_CLOSED: A: %d: %s', ledger_closed_index, ledger_closed); // callback(); // }) - // .ledger_accept(); // }, // function (callback) { - // self.what = "Verify balance from alice's pov: 5"; + // self.what = 'Verify balance from alice's pov: 5'; // - // $.remote.request_ripple_balance("alice", "bob", "USD", 'CURRENT') + // $.remote.request_ripple_balance('alice', 'bob', 'USD', 'CURRENT') // .once('ripple_state', function (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("peer_balance: %s", m.peer_balance.to_text_full()); - // console.log("peer_limit: %s", m.peer_limit.to_text_full()); + // console.log('account_balance: %s', m.account_balance.to_text_full()); + // console.log('account_limit: %s', m.account_limit.to_text_full()); + // console.log('peer_balance: %s', m.peer_balance.to_text_full()); + // console.log('peer_limit: %s', m.peer_limit.to_text_full()); // - // assert(m.account_balance.equals("600/USD/alice")); + // assert(m.account_balance.equals('600/USD/alice')); // // callback(); // }) @@ -440,8 +421,8 @@ suite('Sending future', function() { // }, ] - async.waterfall(steps, function(error) { - assert(!error, self.what); + async.series(steps, function(err) { + assert(!err, self.what + ': ' + err); done(); }); }); @@ -458,116 +439,117 @@ suite('Gateway', function() { testutils.build_teardown().call($, done); }); - test("customer to customer with and without transfer fee", function (done) { + test('customer to customer with and without transfer fee', function (done) { var self = this; // $.remote.set_trace(); var steps = [ function (callback) { - self.what = "Create accounts."; - testutils.create_accounts($.remote, "root", "10000.0", ["alice", "bob", "mtgox"], callback); + self.what = 'Create accounts.'; + testutils.create_accounts($.remote, 'root', '10000.0', ['alice', 'bob', 'mtgox'], callback); }, function (callback) { - self.what = "Set credit limits."; + self.what = 'Set credit limits.'; testutils.credit_limits($.remote, { - "alice" : "100/AUD/mtgox", - "bob" : "100/AUD/mtgox", + 'alice' : '100/AUD/mtgox', + 'bob' : '100/AUD/mtgox', }, callback); }, function (callback) { - self.what = "Distribute funds."; + self.what = 'Distribute funds.'; testutils.payments($.remote, { - "mtgox" : [ "1/AUD/alice" ], + 'mtgox' : [ '1/AUD/alice' ], }, callback); }, function (callback) { - self.what = "Verify balances."; + self.what = 'Verify balances.'; testutils.verify_balances($.remote, { - "alice" : "1/AUD/mtgox", - "mtgox" : "-1/AUD/alice", + 'alice' : '1/AUD/mtgox', + 'mtgox' : '-1/AUD/alice', }, callback); }, function (callback) { - self.what = "Alice sends Bob 1 AUD"; + self.what = 'Alice sends Bob 1 AUD'; $.remote.transaction() - .payment("alice", "bob", "1/AUD/mtgox") - .once('proposed', function (m) { - // console.log("proposed: %s", JSON.stringify(m)); - - callback(m.engine_result !== 'tesSUCCESS'); + .payment('alice', 'bob', '1/AUD/mtgox') + .once('final', function (m) { + // console.log('proposed: %s', JSON.stringify(m)); + assert.strictEqual(m.engine_result, 'tesSUCCESS'); + callback(); }) .submit(); }, function (callback) { - self.what = "Verify balances 2."; + self.what = 'Verify balances 2.'; testutils.verify_balances($.remote, { - "alice" : "0/AUD/mtgox", - "bob" : "1/AUD/mtgox", - "mtgox" : "-1/AUD/bob", + 'alice' : '0/AUD/mtgox', + 'bob' : '1/AUD/mtgox', + 'mtgox' : '-1/AUD/bob', }, callback); }, function (callback) { - self.what = "Set transfer rate."; + self.what = 'Set transfer rate.'; $.remote.transaction() - .account_set("mtgox") + .account_set('mtgox') .transfer_rate(1e9*1.1) - .once('proposed', function (m) { - // console.log("proposed: %s", JSON.stringify(m)); - callback(m.engine_result !== 'tesSUCCESS'); + .once('final', function (m) { + // console.log('proposed: %s', JSON.stringify(m)); + assert.strictEqual(m.engine_result, 'tesSUCCESS'); + callback(); }) .submit(); }, function (callback) { - self.what = "Bob sends Alice 0.5 AUD"; + self.what = 'Bob sends Alice 0.5 AUD'; $.remote.transaction() - .payment("bob", "alice", "0.5/AUD/mtgox") - .send_max("0.55/AUD/mtgox") // !!! Very important. - .once('proposed', function (m) { - // console.log("proposed: %s", JSON.stringify(m)); - - callback(m.engine_result !== 'tesSUCCESS'); + .payment('bob', 'alice', '0.5/AUD/mtgox') + .send_max('0.55/AUD/mtgox') // !!! Very important. + .once('final', function (m) { + // console.log('proposed: %s', JSON.stringify(m)); + assert.strictEqual(m.engine_result, 'tesSUCCESS'); + callback(); }) .submit(); }, function (callback) { - self.what = "Verify balances 3."; + self.what = 'Verify balances 3.'; testutils.verify_balances($.remote, { - "alice" : "0.5/AUD/mtgox", - "bob" : "0.45/AUD/mtgox", - "mtgox" : [ "-0.5/AUD/alice","-0.45/AUD/bob" ], + 'alice' : '0.5/AUD/mtgox', + 'bob' : '0.45/AUD/mtgox', + 'mtgox' : [ '-0.5/AUD/alice','-0.45/AUD/bob' ], }, callback); }, ] - async.waterfall(steps, function(error) { - assert(!error, self.what); + async.series(steps, function(err) { + assert(!err, self.what + ': ' + err); done(); }); }); - test("customer to customer, transfer fee, default path with and without specific issuer for Amount and SendMax", function (done) { + test('customer to customer, transfer fee, default path with and without specific issuer for Amount and SendMax', function (done) { var self = this; @@ -575,300 +557,316 @@ suite('Gateway', function() { var steps = [ function (callback) { - self.what = "Create accounts."; - testutils.create_accounts($.remote, "root", "10000.0", ["alice", "bob", "mtgox"], callback); + self.what = 'Create accounts.'; + testutils.create_accounts($.remote, 'root', '10000.0', ['alice', 'bob', 'mtgox'], callback); }, function (callback) { - self.what = "Set transfer rate."; + self.what = 'Set transfer rate.'; $.remote.transaction() - .account_set("mtgox") + .account_set('mtgox') .transfer_rate(1e9*1.1) - .once('submitted', function (m) { - // console.log("submitted: %s", JSON.stringify(m)); - callback(m.engine_result !== 'tesSUCCESS'); + .once('final', function (m) { + // console.log('submitted: %s', JSON.stringify(m)); + assert.strictEqual(m.engine_result, 'tesSUCCESS'); + callback(); }) .submit(); }, function (callback) { - self.what = "Set credit limits."; + self.what = 'Set credit limits.'; testutils.credit_limits($.remote, { - "alice" : "100/AUD/mtgox", - "bob" : "100/AUD/mtgox", + 'alice' : '100/AUD/mtgox', + 'bob' : '100/AUD/mtgox', }, callback); }, function (callback) { - self.what = "Distribute funds."; + self.what = 'Distribute funds.'; testutils.payments($.remote, { - "mtgox" : [ "4.4/AUD/alice" ], + 'mtgox' : [ '4.4/AUD/alice' ], }, callback); }, function (callback) { - self.what = "Verify balances."; + self.what = 'Verify balances.'; testutils.verify_balances($.remote, { - "alice" : "4.4/AUD/mtgox", + 'alice' : '4.4/AUD/mtgox', }, callback); }, function (callback) { - self.what = "Alice sends 1.1/AUD/mtgox Bob 1/AUD/mtgox"; + self.what = 'Alice sends 1.1/AUD/mtgox Bob 1/AUD/mtgox'; $.remote.transaction() - .payment("alice", "bob", "1/AUD/mtgox") - .send_max("1.1/AUD/mtgox") - .once('submitted', function (m) { - // console.log("submitted: %s", JSON.stringify(m)); - - callback(m.engine_result !== 'tesSUCCESS'); + .payment('alice', 'bob', '1/AUD/mtgox') + .send_max('1.1/AUD/mtgox') + .once('final', function (m) { + // console.log('submitted: %s', JSON.stringify(m)); + assert.strictEqual(m.engine_result, 'tesSUCCESS'); + callback(); }) .submit(); }, function (callback) { - self.what = "Verify balances 2."; + self.what = 'Verify balances 2.'; testutils.verify_balances($.remote, { - "alice" : "3.3/AUD/mtgox", - "bob" : "1/AUD/mtgox", + 'alice' : '3.3/AUD/mtgox', + 'bob' : '1/AUD/mtgox', }, callback); }, function (callback) { - self.what = "Alice sends 1.1/AUD/mtgox Bob 1/AUD/bob"; + self.what = 'Alice sends 1.1/AUD/mtgox Bob 1/AUD/bob'; $.remote.transaction() - .payment("alice", "bob", "1/AUD/bob") - .send_max("1.1/AUD/mtgox") - .once('submitted', function (m) { - // console.log("submitted: %s", JSON.stringify(m)); - - callback(m.engine_result !== 'tesSUCCESS'); + .payment('alice', 'bob', '1/AUD/bob') + .send_max('1.1/AUD/mtgox') + .once('final', function (m) { + // console.log('submitted: %s', JSON.stringify(m)); + assert.strictEqual(m.engine_result, 'tesSUCCESS'); + callback(); }) .submit(); }, function (callback) { - self.what = "Verify balances 3."; + self.what = 'Verify balances 3.'; testutils.verify_balances($.remote, { - "alice" : "2.2/AUD/mtgox", - "bob" : "2/AUD/mtgox", + 'alice' : '2.2/AUD/mtgox', + 'bob' : '2/AUD/mtgox', }, callback); }, function (callback) { - self.what = "Alice sends 1.1/AUD/alice Bob 1/AUD/mtgox"; + self.what = 'Alice sends 1.1/AUD/alice Bob 1/AUD/mtgox'; $.remote.transaction() - .payment("alice", "bob", "1/AUD/mtgox") - .send_max("1.1/AUD/alice") - .once('submitted', function (m) { - // console.log("submitted: %s", JSON.stringify(m)); - - callback(m.engine_result !== 'tesSUCCESS'); + .payment('alice', 'bob', '1/AUD/mtgox') + .send_max('1.1/AUD/alice') + .once('final', function (m) { + // console.log('submitted: %s', JSON.stringify(m)); + assert.strictEqual(m.engine_result, 'tesSUCCESS'); + callback(); }) .submit(); }, function (callback) { - self.what = "Verify balances 4."; + self.what = 'Verify balances 4.'; testutils.verify_balances($.remote, { - "alice" : "1.1/AUD/mtgox", - "bob" : "3/AUD/mtgox", + 'alice' : '1.1/AUD/mtgox', + 'bob' : '3/AUD/mtgox', }, callback); }, function (callback) { // Must fail, doesn't know to use the mtgox - self.what = "Alice sends 1.1/AUD/alice Bob 1/AUD/bob"; + self.what = 'Alice sends 1.1/AUD/alice Bob 1/AUD/bob'; $.remote.transaction() - .payment("alice", "bob", "1/AUD/bob") - .send_max("1.1/AUD/alice") - .once('submitted', function (m) { - // console.log("submitted: %s", JSON.stringify(m)); - - callback(m.engine_result !== 'tecPATH_DRY'); + .payment('alice', 'bob', '1/AUD/bob') + .send_max('1.1/AUD/alice') + .once('final', function (m) { + // console.log('submitted: %s', JSON.stringify(m)); + assert.strictEqual(m.engine_result, 'tecPATH_DRY'); + callback(); }) .submit(); }, function (callback) { - self.what = "Verify balances 5."; + self.what = 'Verify balances 5.'; testutils.verify_balances($.remote, { - "alice" : "1.1/AUD/mtgox", - "bob" : "3/AUD/mtgox", + 'alice' : '1.1/AUD/mtgox', + 'bob' : '3/AUD/mtgox', }, callback); } ] - async.waterfall(steps, function(error) { - assert(!error, self.what); + async.series(steps, function(err) { + assert(!err, self.what + ': ' + err); done(); }); }); - test("subscribe test customer to customer with and without transfer fee", function (done) { + test('subscribe test customer to customer with and without transfer fee', function (done) { var self = this; // $.remote.set_trace(); var steps = [ function (callback) { - self.what = "Create accounts."; - testutils.create_accounts($.remote, "root", "10000.0", ["alice", "bob", "mtgox"], callback); + self.what = 'Create accounts.'; + testutils.create_accounts($.remote, 'root', '10000.0', ['alice', 'bob', 'mtgox'], callback); }, - function (callback) { testutils.ledger_close($.remote, callback); }, + function (callback) { + testutils.ledger_close($.remote, callback); + }, function (callback) { - self.what = "Set credit limits."; + self.what = 'Set credit limits.'; testutils.credit_limits($.remote, { - "alice" : "100/AUD/mtgox", - "bob" : "100/AUD/mtgox", + 'alice' : '100/AUD/mtgox', + 'bob' : '100/AUD/mtgox', }, callback); }, - function (callback) { testutils.ledger_close($.remote, callback); }, + function (callback) { + testutils.ledger_close($.remote, callback); + }, function (callback) { - self.what = "Distribute funds."; + self.what = 'Distribute funds.'; testutils.payments($.remote, { - "mtgox" : [ "1/AUD/alice" ], + 'mtgox' : [ '1/AUD/alice' ], }, callback); }, - function (callback) { testutils.ledger_close($.remote, callback); }, + function (callback) { + testutils.ledger_close($.remote, callback); + }, function (callback) { - self.what = "Verify balances."; + self.what = 'Verify balances.'; testutils.verify_balances($.remote, { - "alice" : "1/AUD/mtgox", - "mtgox" : "-1/AUD/alice", + 'alice' : '1/AUD/mtgox', + 'mtgox' : '-1/AUD/alice', }, callback); }, function (callback) { - self.what = "Alice sends Bob 1 AUD"; + self.what = 'Alice sends Bob 1 AUD'; $.remote.transaction() - .payment("alice", "bob", "1/AUD/mtgox") - .on('proposed', function (m) { - // console.log("proposed: %s", JSON.stringify(m)); - - callback(m.engine_result !== 'tesSUCCESS'); + .payment('alice', 'bob', '1/AUD/mtgox') + .once('final', function (m) { + // console.log('proposed: %s', JSON.stringify(m)); + assert.strictEqual(m.engine_result, 'tesSUCCESS'); + callback(); }) .submit(); }, - function (callback) { testutils.ledger_close($.remote, callback); }, + function (callback) { + testutils.ledger_close($.remote, callback); + }, function (callback) { - self.what = "Verify balances 2."; + self.what = 'Verify balances 2.'; testutils.verify_balances($.remote, { - "alice" : "0/AUD/mtgox", - "bob" : "1/AUD/mtgox", - "mtgox" : "-1/AUD/bob", + 'alice' : '0/AUD/mtgox', + 'bob' : '1/AUD/mtgox', + 'mtgox' : '-1/AUD/bob', }, callback); }, function (callback) { - self.what = "Set transfer rate."; + self.what = 'Set transfer rate.'; $.remote.transaction() - .account_set("mtgox") + .account_set('mtgox') .transfer_rate(1e9*1.1) - .once('proposed', function (m) { - // console.log("proposed: %s", JSON.stringify(m)); - callback(m.engine_result !== 'tesSUCCESS'); + .once('final', function (m) { + // console.log('proposed: %s', JSON.stringify(m)); + assert.strictEqual(m.engine_result, 'tesSUCCESS'); + callback(); }) .submit(); }, - function (callback) { testutils.ledger_close($.remote, callback); }, + function (callback) { + testutils.ledger_close($.remote, callback); + }, function (callback) { - self.what = "Bob sends Alice 0.5 AUD"; + self.what = 'Bob sends Alice 0.5 AUD'; $.remote.transaction() - .payment("bob", "alice", "0.5/AUD/mtgox") - .send_max("0.55/AUD/mtgox") // !!! Very important. - .on('proposed', function (m) { - // console.log("proposed: %s", JSON.stringify(m)); - - callback(m.engine_result !== 'tesSUCCESS'); + .payment('bob', 'alice', '0.5/AUD/mtgox') + .send_max('0.55/AUD/mtgox') // !!! Very important. + .once('submitted', function (m) { + // console.log('proposed: %s', JSON.stringify(m)); + assert.strictEqual(m.engine_result, 'tesSUCCESS'); + callback(); }) .submit(); }, function (callback) { - self.what = "Verify balances 3."; + self.what = 'Verify balances 3.'; testutils.verify_balances($.remote, { - "alice" : "0.5/AUD/mtgox", - "bob" : "0.45/AUD/mtgox", - "mtgox" : [ "-0.5/AUD/alice","-0.45/AUD/bob" ], + 'alice' : '0.5/AUD/mtgox', + 'bob' : '0.45/AUD/mtgox', + 'mtgox' : [ '-0.5/AUD/alice','-0.45/AUD/bob' ], }, callback); }, function (callback) { - self.what = "Subscribe and accept."; + $.remote.request_subscribe().accounts('mtgox').callback(function(err) { + assert(!err); + callback(); + }); + }, + + function (callback) { + self.what = 'Subscribe and accept.'; self.count = 0; self.found = 0; - $.remote - .on('transaction', function (m) { - // console.log("ACCOUNT: %s", JSON.stringify(m)); + $.remote.once('transaction', function (m) { + //console.log('ACCOUNT: %s', JSON.stringify(m)); self.found = 1; - }) - .on('ledger_closed', function (m) { - // console.log("LEDGER_CLOSE: %d: %s", self.count, JSON.stringify(m)); + }); + + $.remote.on('ledger_closed', function (m) { + // console.log('LEDGER_CLOSE: %d: %s', self.count, JSON.stringify(m)); if (self.count) { - callback(!self.found); + assert(self.found); + callback(); } else { self.count = 1; $.remote.ledger_accept(); } - }) - .request_subscribe().accounts("mtgox") - .request(); - - $.remote.ledger_accept(); + }); } ] - async.waterfall(steps, function(error) { - assert(!error, self.what); + async.series(steps, function(err) { + assert(!err, self.what + ': ' + err); done(); }); }); - test("subscribe test: customer to customer with and without transfer fee: transaction retry logic", function (done) { + test('subscribe test: customer to customer with and without transfer fee: transaction retry logic', function (done) { var self = this; @@ -876,114 +874,122 @@ suite('Gateway', function() { var steps = [ function (callback) { - self.what = "Create accounts."; + self.what = 'Create accounts.'; - testutils.create_accounts($.remote, "root", "10000.0", ["alice", "bob", "mtgox"], callback); + testutils.create_accounts($.remote, 'root', '10000.0', ['alice', 'bob', 'mtgox'], callback); }, function (callback) { - self.what = "Set credit limits."; + self.what = 'Set credit limits.'; - testutils.credit_limits($.remote, - { - "alice" : "100/AUD/mtgox", - "bob" : "100/AUD/mtgox", - }, - callback); + testutils.credit_limits($.remote, { + 'alice' : '100/AUD/mtgox', + 'bob' : '100/AUD/mtgox', + }, + callback); }, function (callback) { - self.what = "Distribute funds."; + self.what = 'Distribute funds.'; testutils.payments($.remote, { - "mtgox" : [ "1/AUD/alice" ], + 'mtgox' : [ '1/AUD/alice' ], }, callback); }, function (callback) { - self.what = "Verify balances."; + self.what = 'Verify balances.'; testutils.verify_balances($.remote, { - "alice" : "1/AUD/mtgox", - "mtgox" : "-1/AUD/alice", + 'alice' : '1/AUD/mtgox', + 'mtgox' : '-1/AUD/alice', }, callback); }, function (callback) { - self.what = "Alice sends Bob 1 AUD"; + self.what = 'Alice sends Bob 1 AUD'; $.remote.transaction() - .payment("alice", "bob", "1/AUD/mtgox") - .on('proposed', function (m) { - // console.log("proposed: %s", JSON.stringify(m)); + .payment('alice', 'bob', '1/AUD/mtgox') + .once('final', function (m) { + // console.log('proposed: %s', JSON.stringify(m)); - callback(m.engine_result !== 'tesSUCCESS'); + assert.strictEqual(m.engine_result, 'tesSUCCESS'); + callback(); }) .submit(); }, function (callback) { - self.what = "Verify balances 2."; + self.what = 'Verify balances 2.'; testutils.verify_balances($.remote, { - "alice" : "0/AUD/mtgox", - "bob" : "1/AUD/mtgox", - "mtgox" : "-1/AUD/bob", + 'alice' : '0/AUD/mtgox', + 'bob' : '1/AUD/mtgox', + 'mtgox' : '-1/AUD/bob', }, callback); }, // function (callback) { - // self.what = "Set transfer rate."; + // self.what = 'Set transfer rate.'; // // $.remote.transaction() - // .account_set("mtgox") + // .account_set('mtgox') // .transfer_rate(1e9*1.1) // .once('proposed', function (m) { - // // console.log("proposed: %s", JSON.stringify(m)); + // // console.log('proposed: %s', JSON.stringify(m)); // callback(m.engine_result !== 'tesSUCCESS'); // }) // .submit(); // }, function (callback) { - self.what = "Bob sends Alice 0.5 AUD"; + self.what = 'Bob sends Alice 0.5 AUD'; $.remote.transaction() - .payment("bob", "alice", "0.5/AUD/mtgox") - .on('proposed', function (m) { - // console.log("proposed: %s", JSON.stringify(m)); + .payment('bob', 'alice', '0.5/AUD/mtgox') + .once('submitted', function (m) { + // console.log('proposed: %s', JSON.stringify(m)); - callback(m.engine_result !== 'tesSUCCESS'); + assert.strictEqual(m.engine_result, 'tesSUCCESS'); + callback(); }) .submit(); }, function (callback) { - self.what = "Verify balances 3."; + self.what = 'Verify balances 3.'; testutils.verify_balances($.remote, { - "alice" : "0.5/AUD/mtgox", - "bob" : "0.5/AUD/mtgox", - "mtgox" : [ "-0.5/AUD/alice","-0.5/AUD/bob" ], + 'alice' : '0.5/AUD/mtgox', + 'bob' : '0.5/AUD/mtgox', + 'mtgox' : [ '-0.5/AUD/alice','-0.5/AUD/bob' ], }, callback); }, function (callback) { - self.what = "Subscribe and accept."; + $.remote.request_subscribe().accounts('mtgox').callback(function(err) { + assert(!err); + callback(); + }); + }, + + function (callback) { + self.what = 'Subscribe and accept.'; self.count = 0; self.found = 0; - $.remote - .on('transaction', function (m) { - // console.log("ACCOUNT: %s", JSON.stringify(m)); + $.remote.on('transaction', function (m) { + // console.log('ACCOUNT: %s', JSON.stringify(m)); self.found = 1; - }) - .on('ledger_closed', function (m) { - // console.log("LEDGER_CLOSE: %d: %s", self.count, JSON.stringify(m)); + }); + + $.remote.on('ledger_closed', function (m) { + // console.log('LEDGER_CLOSE: %d: %s', self.count, JSON.stringify(m)); if (self.count) { callback(!self.found); @@ -991,26 +997,23 @@ suite('Gateway', function() { self.count = 1; $.remote.ledger_accept(); } - }) - .request_subscribe().accounts("mtgox") - .request(); - - $.remote.ledger_accept(); + }); }, + function (callback) { - self.what = "Verify balances 4."; + self.what = 'Verify balances 4.'; testutils.verify_balances($.remote, { - "alice" : "0.5/AUD/mtgox", - "bob" : "0.5/AUD/mtgox", - "mtgox" : [ "-0.5/AUD/alice","-0.5/AUD/bob" ], + 'alice' : '0.5/AUD/mtgox', + 'bob' : '0.5/AUD/mtgox', + 'mtgox' : [ '-0.5/AUD/alice','-0.5/AUD/bob' ], }, callback); }, ] - async.waterfall(steps, function (error) { - assert(!error, self.what); + async.series(steps, function (err) { + assert(!err, self.what + ': ' + err); done(); }); }); @@ -1028,269 +1031,315 @@ suite('Indirect ripple', function() { testutils.build_teardown().call($, done); }); - test("indirect ripple", function (done) { + test('indirect ripple', function (done) { var self = this; // $.remote.set_trace(); var steps = [ function (callback) { - self.what = "Create accounts."; + self.what = 'Create accounts.'; - testutils.create_accounts($.remote, "root", "10000.0", ["alice", "bob", "mtgox"], callback); + testutils.create_accounts($.remote, 'root', '10000.0', ['alice', 'bob', 'mtgox'], callback); }, function (callback) { - self.what = "Set credit limits."; + self.what = 'Set credit limits.'; testutils.credit_limits($.remote, { - "alice" : "600/USD/mtgox", - "bob" : "700/USD/mtgox", + 'alice' : '600/USD/mtgox', + 'bob' : '700/USD/mtgox', }, callback); }, function (callback) { - self.what = "Distribute funds."; + self.what = 'Distribute funds.'; testutils.payments($.remote, { - "mtgox" : [ "70/USD/alice", "50/USD/bob" ], + 'mtgox' : [ '70/USD/alice', '50/USD/bob' ], }, callback); }, function (callback) { - self.what = "Verify alice balance with mtgox."; + self.what = 'Verify alice balance with mtgox.'; - testutils.verify_balance($.remote, "alice", "70/USD/mtgox", callback); + testutils.verify_balance($.remote, 'alice', '70/USD/mtgox', callback); }, function (callback) { - self.what = "Verify bob balance with mtgox."; + self.what = 'Verify bob balance with mtgox.'; - testutils.verify_balance($.remote, "bob", "50/USD/mtgox", callback); + testutils.verify_balance($.remote, 'bob', '50/USD/mtgox', callback); }, function (callback) { - self.what = "Alice sends more than has to issuer: 100 out of 70"; + self.what = 'Alice sends more than has to issuer: 100 out of 70'; $.remote.transaction() - .payment("alice", "mtgox", "100/USD/mtgox") - .once('submitted', function (m) { - // console.log("proposed: %s", JSON.stringify(m)); - callback(m.engine_result !== 'tecPATH_PARTIAL'); + .payment('alice', 'mtgox', '100/USD/mtgox') + .once('final', function (m) { + // console.log('proposed: %s', JSON.stringify(m)); + assert.strictEqual(m.engine_result, 'tecPATH_PARTIAL'); + callback(); }) .submit(); }, function (callback) { - self.what = "Alice sends more than has to bob: 100 out of 70"; + self.what = 'Alice sends more than has to bob: 100 out of 70'; $.remote.transaction() - .payment("alice", "bob", "100/USD/mtgox") - .once('submitted', function (m) { - //console.log("proposed: %s", JSON.stringify(m)); - callback(m.engine_result !== 'tecPATH_PARTIAL'); + .payment('alice', 'bob', '100/USD/mtgox') + .once('final', function (m) { + //console.log('proposed: %s', JSON.stringify(m)); + assert.strictEqual(m.engine_result, 'tecPATH_PARTIAL'); + callback(); }) .submit(); } ] - async.waterfall(steps, function(error) { - assert(!error, self.what); + async.series(steps, function(err) { + assert(!err, self.what + ': ' + err); done(); }); }); - test("indirect ripple with path", function (done) { + test('indirect ripple with path', function (done) { var self = this; var steps = [ function (callback) { - self.what = "Create accounts."; + self.what = 'Create accounts.'; - testutils.create_accounts($.remote, "root", "10000.0", ["alice", "bob", "mtgox"], callback); + testutils.create_accounts($.remote, 'root', '10000.0', ['alice', 'bob', 'mtgox'], callback); }, function (callback) { - self.what = "Set credit limits."; + self.what = 'Set credit limits.'; testutils.credit_limits($.remote, { - "alice" : "600/USD/mtgox", - "bob" : "700/USD/mtgox", + 'alice' : '600/USD/mtgox', + 'bob' : '700/USD/mtgox', }, callback); }, function (callback) { - self.what = "Distribute funds."; + self.what = 'Distribute funds.'; testutils.payments($.remote, { - "mtgox" : [ "70/USD/alice", "50/USD/bob" ], + 'mtgox' : [ '70/USD/alice', '50/USD/bob' ], }, callback); }, function (callback) { - self.what = "Alice sends via a path"; + self.what = 'Alice sends via a path'; $.remote.transaction() - .payment("alice", "bob", "5/USD/mtgox") - .path_add( [ { account: "mtgox" } ]) - .on('proposed', function (m) { - // console.log("proposed: %s", JSON.stringify(m)); + .payment('alice', 'bob', '5/USD/mtgox') + .path_add( [ { account: 'mtgox' } ]) + .once('final', function (m) { + // console.log('proposed: %s', JSON.stringify(m)); - callback(m.engine_result !== 'tesSUCCESS'); + assert.strictEqual(m.engine_result, 'tesSUCCESS'); + callback(); }) .submit(); }, function (callback) { - self.what = "Verify alice balance with mtgox."; + self.what = 'Verify alice balance with mtgox.'; - testutils.verify_balance($.remote, "alice", "65/USD/mtgox", callback); + testutils.verify_balance($.remote, 'alice', '65/USD/mtgox', callback); }, function (callback) { - self.what = "Verify bob balance with mtgox."; + self.what = 'Verify bob balance with mtgox.'; - testutils.verify_balance($.remote, "bob", "55/USD/mtgox", callback); + testutils.verify_balance($.remote, 'bob', '55/USD/mtgox', callback); } ] - async.waterfall(steps, function(error) { - assert(!error, self.what); + async.series(steps, function(err) { + assert(!err, self.what + ': ' + err); done(); }); }); - test("indirect ripple with multi path", function (done) { + test('indirect ripple with multi path', function (done) { var self = this; var steps = [ function (callback) { - self.what = "Create accounts."; + self.what = 'Create accounts.'; - testutils.create_accounts($.remote, "root", "10000.0", ["alice", "bob", "carol", "amazon", "mtgox"], callback); + testutils.create_accounts($.remote, 'root', '10000.0', ['alice', 'bob', 'carol', 'amazon', 'mtgox'], callback); }, function (callback) { - self.what = "Set credit limits."; + self.what = 'Set credit limits.'; testutils.credit_limits($.remote, { - "amazon" : "2000/USD/mtgox", - "bob" : [ "600/USD/alice", "1000/USD/mtgox" ], - "carol" : [ "700/USD/alice", "1000/USD/mtgox" ], + 'amazon' : '2000/USD/mtgox', + 'bob' : [ '600/USD/alice', '1000/USD/mtgox' ], + 'carol' : [ '700/USD/alice', '1000/USD/mtgox' ], }, callback); }, function (callback) { - self.what = "Distribute funds."; + self.what = 'Distribute funds.'; testutils.payments($.remote, { - "mtgox" : [ "100/USD/bob", "100/USD/carol" ], + 'mtgox' : [ '100/USD/bob', '100/USD/carol' ], }, callback); }, function (callback) { - self.what = "Alice pays amazon via multiple paths"; + self.what = 'Alice pays amazon via multiple paths'; $.remote.transaction() - .payment("alice", "amazon", "150/USD/mtgox") - .path_add( [ { account: "bob" } ]) - .path_add( [ { account: "carol" } ]) - .on('proposed', function (m) { - // console.log("proposed: %s", JSON.stringify(m)); + .payment('alice', 'amazon', '150/USD/mtgox') + .path_add( [ { account: 'bob' } ]) + .path_add( [ { account: 'carol' } ]) + .once('final', function (m) { + // console.log('proposed: %s', JSON.stringify(m)); - callback(m.engine_result !== 'tesSUCCESS'); + assert.strictEqual(m.engine_result, 'tesSUCCESS'); + callback(); }) .submit(); }, function (callback) { - self.what = "Verify balances."; + self.what = 'Verify balances.'; testutils.verify_balances($.remote, { - "alice" : [ "-100/USD/bob", "-50/USD/carol" ], - "amazon" : "150/USD/mtgox", - "bob" : "0/USD/mtgox", - "carol" : "50/USD/mtgox", + 'alice' : [ '-100/USD/bob', '-50/USD/carol' ], + 'amazon' : '150/USD/mtgox', + 'bob' : '0/USD/mtgox', + 'carol' : '50/USD/mtgox', }, callback); }, ] - async.waterfall(steps, function(error) { - assert(!error, self.what); + async.series(steps, function(err) { + assert(!err, self.what + ': ' + err); done(); }); }); - test("indirect ripple with path and transfer fee", function (done) { + test('indirect ripple with path and transfer fee', function (done) { var self = this; var steps = [ function (callback) { - self.what = "Create accounts."; + self.what = 'Create accounts.'; - testutils.create_accounts($.remote, "root", "10000.0", ["alice", "bob", "carol", "amazon", "mtgox"], callback); + testutils.create_accounts($.remote, 'root', '10000.0', ['alice', 'bob', 'carol', 'amazon', 'mtgox'], callback); }, function (callback) { - self.what = "Set mtgox transfer rate."; + self.what = 'Set mtgox transfer rate.'; - testutils.transfer_rate($.remote, "mtgox", 1.1e9, callback); + testutils.transfer_rate($.remote, 'mtgox', 1.1e9, callback); }, function (callback) { - self.what = "Set credit limits."; + self.what = 'Set credit limits.'; testutils.credit_limits($.remote, { - "amazon" : "2000/USD/mtgox", - "bob" : [ "600/USD/alice", "1000/USD/mtgox" ], - "carol" : [ "700/USD/alice", "1000/USD/mtgox" ], + 'amazon' : '2000/USD/mtgox', + 'bob' : [ '600/USD/alice', '1000/USD/mtgox' ], + 'carol' : [ '700/USD/alice', '1000/USD/mtgox' ], }, callback); }, function (callback) { - self.what = "Distribute funds."; + self.what = 'Distribute funds.'; testutils.payments($.remote, { - "mtgox" : [ "100/USD/bob", "100/USD/carol" ], + 'mtgox' : [ '100/USD/bob', '100/USD/carol' ], }, callback); }, function (callback) { - self.what = "Alice pays amazon via multiple paths"; + self.what = 'Alice pays amazon via multiple paths'; $.remote.transaction() - .payment("alice", "amazon", "150/USD/mtgox") - .send_max("200/USD/alice") - .path_add( [ { account: "bob" } ]) - .path_add( [ { account: "carol" } ]) - .on('proposed', function (m) { - // console.log("proposed: %s", JSON.stringify(m)); - - callback(m.engine_result !== 'tesSUCCESS'); + .payment('alice', 'amazon', '150/USD/mtgox') + .send_max('200/USD/alice') + .path_add( [ { account: 'bob' } ]) + .path_add( [ { account: 'carol' } ]) + .once('final', function (m) { + // console.log('proposed: %s', JSON.stringify(m)); + assert.strictEqual(m.engine_result, 'tesSUCCESS'); + callback(); }) .submit(); }, // function (callback) { - // self.what = "Display ledger"; + // self.what = 'Display ledger'; // // $.remote.request_ledger('current', true) // .on('success', function (m) { - // console.log("Ledger: %s", JSON.stringify(m, undefined, 2)); + // console.log('Ledger: %s', JSON.stringify(m, undefined, 2)); // // callback(); // }) // .request(); // }, function (callback) { - self.what = "Verify balances."; + self.what = 'Verify balances.'; // 65.00000000000001 is correct. // This is result of limited precision. testutils.verify_balances($.remote, { - "alice" : [ "-100/USD/bob", "-65.00000000000001/USD/carol" ], - "amazon" : "150/USD/mtgox", - "bob" : "0/USD/mtgox", - "carol" : "35/USD/mtgox", + 'alice' : [ '-100/USD/bob', '-65.00000000000001/USD/carol' ], + 'amazon' : '150/USD/mtgox', + 'bob' : '0/USD/mtgox', + 'carol' : '35/USD/mtgox', }, callback); } ] - async.waterfall(steps, function(error) { - assert(!error, self.what); + async.series(steps, function(err) { + assert(!err, self.what + ': ' + err); done(); }); }) }); + +suite('Invoice ID', function() { + var $ = { }; + + setup(function(done) { + testutils.build_setup().call($, done); + }); + + teardown(function(done) { + testutils.build_teardown().call($, done); + }); + + test('set InvoiceID on payment', 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 = 'Send a payment with InvoiceID'; + + var tx = $.remote.transaction(); + tx.payment('root', 'alice', '10000'); + tx.invoiceID('DEADBEEF'); + tx.submit(function(err, res) { + assert(!err); + assert.strictEqual(res.transaction.InvoiceID, 'DEADBEEF00000000000000000000000000000000000000000000000000000000'); + done(); + }); + } + ] + + async.series(steps, function(err) { + assert(!err, self.what + ': ' + err); + done(); + }); + }); +}); + // vim:sw=2:sts=2:ts=8:et diff --git a/test/server.js b/test/server.js index 050a55bc1..0a1d60488 100644 --- a/test/server.js +++ b/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,8 +34,7 @@ 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(); } @@ -47,8 +46,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.'; } }; @@ -59,23 +58,24 @@ 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; - 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); + 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); }; // 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,42 +97,56 @@ 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 = []; - self.child.stderr.on('data', function(buf) { stderr.push(buf); }); + } + + var stderr = [ ]; + var ended = false; + + this.child.stderr.on('data', function(data) { + stderr.push(data); + }); + + this.child.stderr.on('end', function() { + ended = true; + }); // By default, just log exits. - this.child.on('exit', function(code, signal) { - if (!self.quiet) console.log("server: spawn: server exited code=%s: signal=%s", code, signal); + 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); + } self.emit('exited'); // Dump server logs on an abnormal exit - 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 (self.quiet && !self.stopping) { + process.stdout.write('rippled stderr:\n'); + process.stdout.write(stderr.join('')); }; // 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) { @@ -142,7 +156,7 @@ Server.prototype._makeBase = function (done) { }; Server.prototype.verbose = function () { - this.quiet = false; + this.quiet = false; return this; }; @@ -150,9 +164,14 @@ 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; @@ -167,20 +186,25 @@ Server.prototype.start = function () { Server.prototype.stop = function () { var self = this; - self.stopping = true; - if (!this.child) { - console.log("server: stop: can't stop"); - return; + if (!self.quiet) { + console.log('server: stop: can\'t stop'); + } + return this; } + self.stopping = true; + // Update the on exit to invoke done. - this.child.on('exit', function (code, signal) { - if (!self.quiet) console.log("server: stop: server exited"); + function childExited(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; diff --git a/test/testutils.js b/test/testutils.js index db3eee8fa..53e634f7e 100644 --- a/test/testutils.js +++ b/test/testutils.js @@ -42,13 +42,7 @@ function account_dump(remote, account, callback) { request.account_root('root'); request.callback(function(err, r) { assert(!err, self.what); - if (err) { - //console.log('error: %s', m); - callback(err); - } else { - //console.log('account_root: %s', JSON.stringify(r, undefined, 2)); - callback(); - } + callback(err); }); // get closed ledger hash @@ -137,11 +131,21 @@ function build_setup(opts, host) { function connect_websocket(callback) { self.remote = data.remote = Remote.from_config(host, !!opts.verbose_ws); - self.remote.once('ledger_closed', function(ledger) { - callback(); - }); - self.remote.connect(); + 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) { + self.ledger_interval = setInterval(function() { + self.remote.ledger_accept(); + }, 200); + callback(); } + ]; async.series(series, done); @@ -160,16 +164,19 @@ 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) { + clearInterval(self.ledger_interval); + callback(); + }, + function disconnect_websocket(callback) { data.remote.once('disconnected', callback) - data.remote.once('error', function (m) { - //console.log('server error: ', m); - }) - data.remote.connect(false); + data.remote.disconnect(); }, function stop_server(callback) { @@ -190,35 +197,25 @@ function build_teardown(host) { }; function create_accounts(remote, src, amount, accounts, callback) { - assert(arguments.length === 5); + assert.strictEqual(arguments.length, 5); remote.set_account_seq(src, 1); - async.forEach(accounts, function (account, callback) { + async.forEach(accounts, function (account, nextAccount) { // 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.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(arguments.length === 4); + assert.strictEqual(arguments.length, 4); var _m = amount.match(/^(\d+\/...\/[^\:]+)(?::(\d+)(?:,(\d+))?)?$/); @@ -232,25 +229,24 @@ 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.once('proposed', function (m) { - // console.log('proposed: %s', JSON.stringify(m)); - callback(m.engine_result === 'tesSUCCESS' ? null : new Error()); + 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('error', function (m) { - // console.log('error: %s', JSON.stringify(m)); - callback(m); - }); - - tx.submit(); }; function verify_limit(remote, src, amount, callback) { - assert(arguments.length === 4); + assert.strictEqual(arguments.length, 4); var _m = amount.match(/^(\d+\/...\/[^\:]+)(?::(\d+)(?:,(\d+))?)?$/); @@ -280,13 +276,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(null); + callback(); } }); }; function credit_limits(remote, balances, callback) { - assert(arguments.length === 3); + assert.strictEqual(arguments.length, 3); var limits = [ ]; @@ -301,7 +297,7 @@ function credit_limits(remote, balances, callback) { function iterator(limit, callback) { credit_limit(remote, limit.source, limit.amount, callback); - } + }; async.some(limits, iterator, callback); }; @@ -314,26 +310,26 @@ function ledger_close(remote, callback) { }; function payment(remote, src, dst, amount, callback) { - assert(arguments.length === 5); + assert.strictEqual(arguments.length, 5); var tx = remote.transaction(); tx.payment(src, dst, amount); - tx.once('proposed', function (m) { + tx.submit(function(err, m) { // console.log('proposed: %s', JSON.stringify(m)); - callback(m.engine_result === 'tesSUCCESS' ? null : new Error()); + if (err) { + callback(err); + } else if (m.engine_result === 'tesSUCCESS') { + callback(); + } else { + callback(m); + } }); - - tx.once('error', function (m) { - // console.log('error: %s', JSON.stringify(m)); - callback(m); - }); - tx.submit(); }; function payments(remote, balances, callback) { - assert(arguments.length === 3); + assert.strictEqual(arguments.length, 3); var sends = [ ]; @@ -349,7 +345,7 @@ function payments(remote, balances, callback) { function iterator(send, callback) { payment(remote, send.source, send.destination, send.amount, callback); - } + }; async.some(sends, iterator, callback); }; @@ -360,63 +356,39 @@ function transfer_rate(remote, src, billionths, callback) { var tx = remote.transaction(); tx.account_set(src); tx.transfer_rate(billionths); - - 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(); + tx.submit(callback); }; function verify_balance(remote, src, amount_json, callback) { - assert(arguments.length === 4); + assert.strictEqual(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) { - 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()); + assert.ifError(err); + assert.strictEqual(amount_act.to_json(), amount_req.to_json()); + callback(); }); } 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) { - //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)); + if (valid_balance) { + callback(); + } else { + callback(new Error('Invalid balance: ' + amount_req.to_text() + '/' + Amount.from_json(account_balance).to_text())); } - - callback(valid_balance ? null : new Error()); }) } }; @@ -432,9 +404,9 @@ function verify_balances(remote, balances, callback) { function iterator(test, callback) { verify_balance(remote, test.source, test.amount, callback) - } + }; - async.every(tests, iterator, callback); + async.eachSeries(tests, iterator, callback); }; // --> owner: account @@ -442,7 +414,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(arguments.length === 6); + assert.strictEqual(arguments.length, 6); var request = remote.request_ledger_entry('offer') request.offer_id(owner, seq) @@ -453,43 +425,41 @@ 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(arguments.length === 4); + assert.strictEqual(arguments.length, 4); var request = remote.request_ledger_entry('offer'); - request.offer_id(owner, seq); - - 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); + request.callback(function(err, m) { + if (err && err.error === 'remoteError' && err.remote.error === 'entryNotFound') { + callback(); } else { - callback(new Error()); + callback(new Error('Expected remoteError entryNotFound: ' + m)); } }); - - request.request(); }; function verify_owner_count(remote, account, count, callback) { - assert(arguments.length === 4); + assert.strictEqual(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); - callback(owner_count === count ? null : new Error()); + if (err) { + callback(err); + } else if (owner_count !== count) { + callback(new Error('Owner count mismatch: ' + owner_count + '/' + count)); + } else { + callback(); + } }); }; @@ -500,9 +470,15 @@ function verify_owner_counts(remote, counts, callback) { function iterator(test, callback) { verify_owner_count(remote, test.account, test.count, callback) - } + }; - async.every(tests, iterator, callback); + async.eachSeries(tests, iterator, function(err) { + if (err) { + callback(); + } else { + callback(new Error('Owner counts mismatch')); + } + }); }; exports.account_dump = account_dump;