mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-20 11:05:54 +00:00
Update account_objects test:
* Use Request over json-rpc * Use lodash to filter irrelevant fields from expectations * Use LedgerState for state setup * Test using limit and marker Conflicts: test/account_objects-test.js
This commit is contained in:
committed by
Vinnie Falco
parent
4d0ed3d857
commit
4c5308da8d
@@ -10,6 +10,7 @@
|
|||||||
"async": "~0.2.9",
|
"async": "~0.2.9",
|
||||||
"deep-equal": "0.0.0",
|
"deep-equal": "0.0.0",
|
||||||
"extend": "~1.2.0",
|
"extend": "~1.2.0",
|
||||||
|
"lodash": "^3.5.0",
|
||||||
"request": "^2.47.0",
|
"request": "^2.47.0",
|
||||||
"ripple-lib": "0.10.0",
|
"ripple-lib": "0.10.0",
|
||||||
"simple-jsonrpc": "~0.0.2"
|
"simple-jsonrpc": "~0.0.2"
|
||||||
|
|||||||
@@ -1,237 +1,288 @@
|
|||||||
var async = require("async");
|
/* -------------------------------- REQUIRES -------------------------------- */
|
||||||
var assert = require('assert');
|
|
||||||
var http = require("http");
|
var async = require('async');
|
||||||
var jsonrpc = require("simple-jsonrpc");
|
var assert = require('assert-diff');
|
||||||
var EventEmitter = require('events').EventEmitter;
|
var lodash = require('lodash');
|
||||||
var Remote = require("ripple-lib").Remote;
|
|
||||||
var testutils = require("./testutils");
|
var Remote = require('ripple-lib').Remote;
|
||||||
|
var Request = require('ripple-lib').Request;
|
||||||
|
var Account = require('ripple-lib').UInt160;
|
||||||
|
var testutils = require('./testutils');
|
||||||
|
var LedgerState = require('./ledger-state').LedgerState;
|
||||||
|
|
||||||
var config = testutils.init_config();
|
var config = testutils.init_config();
|
||||||
|
// We just use equal instead of strictEqual everywhere.
|
||||||
|
assert.options.strict = true;
|
||||||
|
|
||||||
function build_setup(options) {
|
/* --------------------------------- HELPERS -------------------------------- */
|
||||||
var setup = testutils.build_setup(options);
|
|
||||||
|
|
||||||
return function (done) {
|
function noop() {}
|
||||||
var self = this;
|
|
||||||
|
|
||||||
var http_config = config.http_servers["zed"];
|
function account_objects(remote, account, params, callback) {
|
||||||
|
if (lodash.isFunction(params)) {
|
||||||
|
callback = params;
|
||||||
|
params = null;
|
||||||
|
}
|
||||||
|
|
||||||
self.server_events = new EventEmitter;
|
var request = new Request(remote, 'account_objects');
|
||||||
|
request.message.account = Account.json_rewrite(account);
|
||||||
|
lodash.forOwn(params || {}, function(v, k) { request.message[k] = v; });
|
||||||
|
|
||||||
self.server = http.createServer(function (req, res) {
|
request.callback(callback);
|
||||||
// console.log("REQUEST");
|
}
|
||||||
var input = "";
|
|
||||||
|
|
||||||
req.setEncoding('utf8');
|
function filter_threading_fields(entries) {
|
||||||
|
return entries.map(function(entry) {
|
||||||
req.on('data', function (buffer) {
|
return lodash.omit(entry, ['PreviousTxnID', 'PreviousTxnLgrSeq']);
|
||||||
// console.log("DATA: %s", buffer);
|
|
||||||
input = input + buffer;
|
|
||||||
});
|
|
||||||
|
|
||||||
req.on('end', function () {
|
|
||||||
var request = JSON.parse(input);
|
|
||||||
// console.log("REQ: %s", JSON.stringify(request, undefined, 2));
|
|
||||||
self.server_events.emit('request', request, res);
|
|
||||||
});
|
|
||||||
|
|
||||||
req.on('close', function () { });
|
|
||||||
});
|
|
||||||
|
|
||||||
self.server.listen(http_config.port, http_config.ip, void(0), function () {
|
|
||||||
// console.log("server up: %s %d", http_config.ip, http_config.port);
|
|
||||||
setup.call(self, done);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
function build_teardown() {
|
|
||||||
var teardown = testutils.build_teardown();
|
|
||||||
|
|
||||||
return function (done) {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
self.server.close(function () {
|
|
||||||
// console.log("server closed");
|
|
||||||
|
|
||||||
teardown.call(self, done);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
suite('ACCOUNT_OBJECTS', function() {
|
|
||||||
var $ = { };
|
|
||||||
|
|
||||||
setup(function(done) {
|
|
||||||
build_setup().call($, done);
|
|
||||||
});
|
|
||||||
|
|
||||||
teardown(function(done) {
|
|
||||||
build_teardown().call($, done);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('account_objects', function(done) {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
var rippled_config = testutils.get_server_config(config);
|
|
||||||
var client = jsonrpc.client("http://" + rippled_config.rpc_ip + ":" +
|
|
||||||
rippled_config.rpc_port);
|
|
||||||
var http_config = config.http_servers["zed"];
|
|
||||||
|
|
||||||
var steps = [
|
|
||||||
function (callback) {
|
|
||||||
self.what = 'Create accounts';
|
|
||||||
|
|
||||||
testutils.create_accounts(
|
|
||||||
$.remote,
|
|
||||||
'root',
|
|
||||||
'20000.0',
|
|
||||||
[ 'mtgox', 'alice', 'bob' ],
|
|
||||||
callback
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
function waitLedgers(callback) {
|
|
||||||
self.what = 'Wait ledger';
|
|
||||||
|
|
||||||
$.remote.once('ledger_closed', function() {
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
|
|
||||||
$.remote.ledger_accept();
|
|
||||||
},
|
|
||||||
|
|
||||||
function verifyBalance(callback) {
|
|
||||||
self.what = 'Verify balance';
|
|
||||||
|
|
||||||
testutils.verify_balance(
|
|
||||||
$.remote,
|
|
||||||
[ 'mtgox', 'alice', 'bob' ],
|
|
||||||
'19999999988',
|
|
||||||
callback
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
function (callback) {
|
|
||||||
self.what = 'Set transfer rate';
|
|
||||||
|
|
||||||
var tx = $.remote.transaction('AccountSet', {
|
|
||||||
account: 'mtgox'
|
|
||||||
});
|
|
||||||
|
|
||||||
tx.transferRate(1.1 * 1e9);
|
|
||||||
|
|
||||||
tx.submit(function(err, m) {
|
|
||||||
assert.ifError(err);
|
|
||||||
assert.strictEqual(m.engine_result, 'tesSUCCESS');
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
|
|
||||||
testutils.ledger_wait($.remote, tx);
|
|
||||||
},
|
|
||||||
|
|
||||||
function (callback) {
|
|
||||||
self.what = 'Set limits';
|
|
||||||
|
|
||||||
testutils.credit_limits($.remote, {
|
|
||||||
'alice' : '1000/USD/mtgox',
|
|
||||||
'bob' : '1000/USD/mtgox'
|
|
||||||
},
|
|
||||||
callback);
|
|
||||||
},
|
|
||||||
|
|
||||||
function (callback) {
|
|
||||||
self.what = 'Distribute funds';
|
|
||||||
|
|
||||||
testutils.payments($.remote, {
|
|
||||||
'mtgox' : [ '100/USD/alice', '50/USD/bob' ]
|
|
||||||
},
|
|
||||||
callback);
|
|
||||||
},
|
|
||||||
|
|
||||||
function (callback) {
|
|
||||||
self.what = 'Create offer';
|
|
||||||
|
|
||||||
// get 4000/XRP pay 10/USD : offer pays 10 USD for 4000 XRP
|
|
||||||
var tx = $.remote.transaction('OfferCreate', {
|
|
||||||
account: 'alice',
|
|
||||||
taker_pays: '4000',
|
|
||||||
taker_gets: '10/USD/mtgox'
|
|
||||||
});
|
|
||||||
|
|
||||||
tx.submit(function(err, m) {
|
|
||||||
assert.ifError(err);
|
|
||||||
assert.strictEqual(m.engine_result, 'tesSUCCESS');
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
|
|
||||||
testutils.ledger_wait($.remote, tx);
|
|
||||||
},
|
|
||||||
|
|
||||||
function (callback) {
|
|
||||||
self.what = "Get account objects.";
|
|
||||||
|
|
||||||
client.call('account_objects', [{
|
|
||||||
"account": "rG1QQv2nh2gr7RCZ1P8YYcBUKCCN633jCn",
|
|
||||||
"limit": 10
|
|
||||||
}], function (result) {
|
|
||||||
// console.log(JSON.stringify(result, undefined, 2));
|
|
||||||
assert(typeof result === 'object');
|
|
||||||
|
|
||||||
assert('account' in result);
|
|
||||||
assert.deepEqual(result['account'], 'rG1QQv2nh2gr7RCZ1P8YYcBUKCCN633jCn');
|
|
||||||
|
|
||||||
assert('account_objects' in result);
|
|
||||||
var expected = [{
|
|
||||||
Balance: {
|
|
||||||
currency: 'USD',
|
|
||||||
issuer: 'rrrrrrrrrrrrrrrrrrrrBZbvji',
|
|
||||||
value: '-100'
|
|
||||||
},
|
|
||||||
Flags: 131072,
|
|
||||||
HighLimit: {
|
|
||||||
currency: 'USD',
|
|
||||||
issuer: 'rG1QQv2nh2gr7RCZ1P8YYcBUKCCN633jCn',
|
|
||||||
value: '1000'
|
|
||||||
},
|
|
||||||
HighNode: '0000000000000000',
|
|
||||||
LedgerEntryType: 'RippleState',
|
|
||||||
LowLimit: {
|
|
||||||
currency: 'USD',
|
|
||||||
issuer: 'rGihwhaqU8g7ahwAvTq6iX5rvsfcbgZw6v',
|
|
||||||
value: '0'
|
|
||||||
},
|
|
||||||
LowNode: '0000000000000000',
|
|
||||||
PreviousTxnID: result['account_objects'][0]['PreviousTxnID'],
|
|
||||||
PreviousTxnLgrSeq: result['account_objects'][0]['PreviousTxnLgrSeq'],
|
|
||||||
index: 'DE9CF5B006C8EA021CAB2ED20F01FC9D3260875C885155E7FA7A4DB534E36D8A'
|
|
||||||
}, {
|
|
||||||
Account: 'rG1QQv2nh2gr7RCZ1P8YYcBUKCCN633jCn',
|
|
||||||
BookDirectory:
|
|
||||||
'AE0A97F385FFE42E3096BA3F98A0173090FE66A3C2482FE0570E35FA931A0000',
|
|
||||||
BookNode: '0000000000000000',
|
|
||||||
Flags: 0,
|
|
||||||
LedgerEntryType: 'Offer',
|
|
||||||
OwnerNode: '0000000000000000',
|
|
||||||
PreviousTxnID: result['account_objects'][1]['PreviousTxnID'],
|
|
||||||
PreviousTxnLgrSeq: result['account_objects'][1]['PreviousTxnLgrSeq'],
|
|
||||||
Sequence: 3,
|
|
||||||
TakerGets: {
|
|
||||||
currency: 'USD',
|
|
||||||
issuer: 'rGihwhaqU8g7ahwAvTq6iX5rvsfcbgZw6v',
|
|
||||||
value: '10'
|
|
||||||
},
|
|
||||||
TakerPays: '4000',
|
|
||||||
index: '2A432F386EF28151AF60885CE201CC9331FF494A163D40531A9D253C97E81D61'
|
|
||||||
}];
|
|
||||||
|
|
||||||
assert.deepEqual(result['account_objects'], expected);
|
|
||||||
callback();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------- TEST ---------------------------------- */
|
||||||
|
|
||||||
|
suite('account_objects', function() {
|
||||||
|
// A declarative description of the ledger
|
||||||
|
var ledger_state = {
|
||||||
|
accounts: {
|
||||||
|
// Gateways
|
||||||
|
G1 : {balance: ["1000.0"]},
|
||||||
|
G2 : {balance: ["1000.0"]},
|
||||||
|
|
||||||
|
// Bob has two RippleState and two Offer account objects.
|
||||||
|
bob : {
|
||||||
|
balance: ["1000.0", "1000/USD/G1",
|
||||||
|
"1000/USD/G2"],
|
||||||
|
// these offers will be in `Sequence`
|
||||||
|
offers: [["100.0", "1/USD/bob"],
|
||||||
|
["100.0", "1/USD/G1"]]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// build_(setup|teardown) utils functions set state on this context var.
|
||||||
|
var context = {};
|
||||||
|
|
||||||
|
// After setup we bind the remote to `account_objects` helper above.
|
||||||
|
var request_account_objects;
|
||||||
|
var bob;
|
||||||
|
var G1;
|
||||||
|
var G2;
|
||||||
|
|
||||||
|
// This runs only once
|
||||||
|
suiteSetup(function(done) {
|
||||||
|
testutils.build_setup().call(context, function() {
|
||||||
|
request_account_objects = account_objects.bind(null, context.remote);
|
||||||
|
var ledger = new LedgerState(ledger_state,
|
||||||
|
assert, context.remote,
|
||||||
|
config);
|
||||||
|
|
||||||
|
// Get references to the account objects for usage later.
|
||||||
|
bob = Account.json_rewrite('bob');
|
||||||
|
G1 = Account.json_rewrite('G1');
|
||||||
|
G2 = Account.json_rewrite('G2');
|
||||||
|
|
||||||
|
// Run the ledger setup util. This compiles the declarative description
|
||||||
|
// into a series of transactions and executes them.
|
||||||
|
ledger.setup(noop /*logger*/, function(){
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
suiteTeardown(function(done) {
|
||||||
|
testutils.build_teardown().call(context, done);
|
||||||
|
});
|
||||||
|
|
||||||
|
// With PreviousTxnID, PreviousTxnLgrSeq omitted.
|
||||||
|
var bobs_objects = [
|
||||||
|
{
|
||||||
|
"Balance": {
|
||||||
|
"currency": "USD",
|
||||||
|
"issuer": "rrrrrrrrrrrrrrrrrrrrBZbvji",
|
||||||
|
"value": "-1000"
|
||||||
|
},
|
||||||
|
"Flags": 131072,
|
||||||
|
"HighLimit": {
|
||||||
|
"currency": "USD",
|
||||||
|
"issuer": "rPMh7Pi9ct699iZUTWaytJUoHcJ7cgyziK",
|
||||||
|
"value": "1000"
|
||||||
|
},
|
||||||
|
"HighNode": "0000000000000000",
|
||||||
|
"LedgerEntryType": "RippleState",
|
||||||
|
"LowLimit": {
|
||||||
|
"currency": "USD",
|
||||||
|
"issuer": "r32rQHyesiTtdWFU7UJVtff4nCR5SHCbJW",
|
||||||
|
"value": "0"
|
||||||
|
},
|
||||||
|
"LowNode": "0000000000000000",
|
||||||
|
"index":
|
||||||
|
"D89BC239086183EB9458C396E643795C1134963E6550E682A190A5F021766D43"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Balance": {
|
||||||
|
"currency": "USD",
|
||||||
|
"issuer": "rrrrrrrrrrrrrrrrrrrrBZbvji",
|
||||||
|
"value": "-1000"
|
||||||
|
},
|
||||||
|
"Flags": 131072,
|
||||||
|
"HighLimit": {
|
||||||
|
"currency": "USD",
|
||||||
|
"issuer": "rPMh7Pi9ct699iZUTWaytJUoHcJ7cgyziK",
|
||||||
|
"value": "1000"
|
||||||
|
},
|
||||||
|
"HighNode": "0000000000000000",
|
||||||
|
"LedgerEntryType": "RippleState",
|
||||||
|
"LowLimit": {
|
||||||
|
"currency": "USD",
|
||||||
|
"issuer": "r9cZvwKU3zzuZK9JFovGg1JC5n7QiqNL8L",
|
||||||
|
"value": "0"
|
||||||
|
},
|
||||||
|
"LowNode": "0000000000000000",
|
||||||
|
"index":
|
||||||
|
"D13183BCFFC9AAC9F96AEBB5F66E4A652AD1F5D10273AEB615478302BEBFD4A4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Account": "rPMh7Pi9ct699iZUTWaytJUoHcJ7cgyziK",
|
||||||
|
"BookDirectory":
|
||||||
|
"50AD0A9E54D2B381288D535EB724E4275FFBF41580D28A925D038D7EA4C68000",
|
||||||
|
"BookNode": "0000000000000000",
|
||||||
|
"Flags": 65536,
|
||||||
|
"LedgerEntryType": "Offer",
|
||||||
|
"OwnerNode": "0000000000000000",
|
||||||
|
"Sequence": 4,
|
||||||
|
"TakerGets": {
|
||||||
|
"currency": "USD",
|
||||||
|
"issuer": "rPMh7Pi9ct699iZUTWaytJUoHcJ7cgyziK",
|
||||||
|
"value": "1"
|
||||||
|
},
|
||||||
|
"TakerPays": "100000000",
|
||||||
|
"index":
|
||||||
|
"A984D036A0E562433A8377CA57D1A1E056E58C0D04818F8DFD3A1AA3F217DD82"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Account": "rPMh7Pi9ct699iZUTWaytJUoHcJ7cgyziK",
|
||||||
|
"BookDirectory":
|
||||||
|
"B025997A323F5C3E03DDF1334471F5984ABDE31C59D463525D038D7EA4C68000",
|
||||||
|
"BookNode": "0000000000000000",
|
||||||
|
"Flags": 65536,
|
||||||
|
"LedgerEntryType": "Offer",
|
||||||
|
"OwnerNode": "0000000000000000",
|
||||||
|
"Sequence": 5,
|
||||||
|
"TakerGets": {
|
||||||
|
"currency": "USD",
|
||||||
|
"issuer": "r32rQHyesiTtdWFU7UJVtff4nCR5SHCbJW",
|
||||||
|
"value": "1"
|
||||||
|
},
|
||||||
|
"TakerPays": "100000000",
|
||||||
|
"index":
|
||||||
|
"CAFE32332D752387B01083B60CC63069BA4A969C9730836929F841450F6A718E"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
test('stepped 1 at a time using marker/limit', function(done) {
|
||||||
|
|
||||||
|
// We step through bob's account objects one at a time by using `limit` and
|
||||||
|
// `marker` and for each object we see, we `push` them onto this array so we
|
||||||
|
// can later check it against an un`limit`ed request.
|
||||||
|
var objects_stepped = [];
|
||||||
|
|
||||||
|
var steps = [
|
||||||
|
function first_ripple_state(next) {
|
||||||
|
request_account_objects('bob', {limit: 1}, function(e, m) {
|
||||||
|
assert.ifError(e);
|
||||||
|
|
||||||
|
var objects = m.account_objects;
|
||||||
|
var ripple_state = m.account_objects[0];
|
||||||
|
|
||||||
|
assert.equal(m.limit, 1);
|
||||||
|
assert.equal(objects.length, 1);
|
||||||
|
assert.equal(ripple_state.LedgerEntryType, 'RippleState');
|
||||||
|
assert.equal(ripple_state.HighLimit.issuer, bob);
|
||||||
|
assert.equal(ripple_state.LowLimit.issuer, G1);
|
||||||
|
|
||||||
|
objects_stepped.push(ripple_state);
|
||||||
|
next(null, m.marker);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
function second_ripple_state(resume_marker, next) {
|
||||||
|
request_account_objects('bob', {limit: 1, marker: resume_marker},
|
||||||
|
function(e, m) {
|
||||||
|
assert.ifError(e);
|
||||||
|
|
||||||
|
var objects = m.account_objects;
|
||||||
|
var ripple_state = m.account_objects[0];
|
||||||
|
|
||||||
|
|
||||||
|
assert.equal(m.limit, 1);
|
||||||
|
assert.equal(objects.length, 1);
|
||||||
|
assert.equal(ripple_state.LedgerEntryType, 'RippleState');
|
||||||
|
assert.equal(ripple_state.HighLimit.issuer, bob);
|
||||||
|
assert.equal(ripple_state.LowLimit.issuer, G2);
|
||||||
|
|
||||||
|
objects_stepped.push(ripple_state);
|
||||||
|
next(null, m.marker);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
function first_offer(resume_marker, next) {
|
||||||
|
request_account_objects('bob', {limit: 1, marker: resume_marker},
|
||||||
|
function(e, m) {
|
||||||
|
assert.ifError(e);
|
||||||
|
|
||||||
|
var objects = m.account_objects;
|
||||||
|
var offer = m.account_objects[0];
|
||||||
|
|
||||||
|
assert.equal(m.limit, 1);
|
||||||
|
assert.equal(objects.length, 1);
|
||||||
|
|
||||||
|
assert.equal(offer.LedgerEntryType, 'Offer');
|
||||||
|
assert.equal(offer.TakerGets.issuer, bob);
|
||||||
|
assert.equal(offer.Account, bob);
|
||||||
|
|
||||||
|
objects_stepped.push(offer);
|
||||||
|
next(null, m.marker);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
function second_offer(resume_marker, next) {
|
||||||
|
request_account_objects('bob', {limit: 1, marker: resume_marker},
|
||||||
|
function(e, m) {
|
||||||
|
assert.ifError(e);
|
||||||
|
|
||||||
|
var objects = m.account_objects;
|
||||||
|
var offer = m.account_objects[0];
|
||||||
|
|
||||||
|
assert.equal(objects.length, 1);
|
||||||
|
|
||||||
|
assert.equal(offer.Account, bob);
|
||||||
|
assert.equal(offer.LedgerEntryType, 'Offer');
|
||||||
|
assert.equal(offer.TakerGets.issuer, G1);
|
||||||
|
|
||||||
|
assert.equal(m.marker, undefined);
|
||||||
|
objects_stepped.push(offer);
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
async.waterfall(steps, function(error) {
|
async.waterfall(steps, function (err, result) {
|
||||||
assert(!error, self.what + ': ' + error);
|
assert.ifError(err);
|
||||||
|
|
||||||
|
var filtered = filter_threading_fields(objects_stepped);
|
||||||
|
// Compare against a known/inspected exchaustive response.
|
||||||
|
assert.deepEqual(filtered, bobs_objects);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('unstepped', function(done) {
|
||||||
|
request_account_objects('bob', function(e, m){
|
||||||
|
var objects = m.account_objects;
|
||||||
|
assert.equal(m.marker, undefined);
|
||||||
|
|
||||||
|
var filtered = filter_threading_fields(objects);
|
||||||
|
// Compare against a known/inspected exchaustive response.
|
||||||
|
assert.deepEqual(filtered, bobs_objects);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user