Initial change from Babel/JS to TypeScript (#70)

* will compile as typescript

* migrated test suite to use JestJS

* Migrated to Jest testing framework and typescript source files

* updated deps

* updated prepublish

* resolved 1 failing test

* changed decimal .0 on four tests, it appears that these were the only four tests expecting integer values to have '.0'

* added linter

* added package-lock

* removed tslint in favor of eslint

* changed yarn to npm

* updated version 2.6->3.0

* removing package lock

* updated node version in nvmrc and jest version in package

* removed nvmrc

* removed some unused functions

* replaced data driven with file from master

* commitint yarn.lock

* removing babel as a dependency in favor of typescript compiling to es5

* removing babel deps

* resolved testing issues by migrating helper function

* added partial linting functionality for test suite

* updated imports for decodeLedgerData

* updated test

* updated yarn.lock

* removed a console.log

* added eslint-jest-plugin to package

* reverting to old linting, will add linting in next PR

* removed comments in shamap

* re-adding .nvmrc

* npm -> yarn

* added . to .eslintrc

* added .eslintrc

* removing linting for this PR

* Changed linting to print a message so that linting doesnt fail in CI

* changing back

* added newline so diff wont show

* removed eslint deps, since linting will be dealt with in a later PR

* changed function calls to describe(...)
This commit is contained in:
Nathan Nichols
2020-06-24 09:00:28 -07:00
parent 16b1b91a76
commit a930b9413c
91 changed files with 5058 additions and 5142 deletions

View File

@@ -1,43 +0,0 @@
const _ = require('lodash');
const assert = require('assert');
const utils = require('./utils');
const {Amount} = require('../src/coretypes');
const {loadFixture} = utils;
const fixtures = loadFixture('data-driven-tests.json');
function amountErrorTests() {
_.filter(fixtures.values_tests, {type: 'Amount'}).forEach(f => {
// We only want these with errors
if (!f.error) {
return
}
const testName = `${JSON.stringify(f.test_json)}\n\tis invalid ` +
`because: ${f.error}`
it(testName, () => {
assert.throws(() => {
Amount.from(f.test_json);
}, JSON.stringify(f.test_json));
});
});
}
describe('Amount', function() {
it('can be parsed from', function() {
assert(Amount.from('1000000') instanceof Amount);
assert.equal(Amount.from('1000000').valueString(), '1000000');
const fixture = {
'value': '1',
'issuer': '0000000000000000000000000000000000000000',
'currency': 'USD'
};
const amt = Amount.from(fixture);
const rewritten = {
'value': '1',
'issuer': 'rrrrrrrrrrrrrrrrrrrrrhoLvTp',
'currency': 'USD'
};
assert.deepEqual(amt.toJSON(), rewritten);
});
amountErrorTests()
});

View File

@@ -0,0 +1,42 @@
const _ = require('lodash')
const { loadFixture } = require('./utils')
const { coreTypes } = require('../dist/types')
const { Amount } = coreTypes
const fixtures = loadFixture('data-driven-tests.json')
function amountErrorTests () {
_.filter(fixtures.values_tests, { type: 'Amount' }).forEach(f => {
// We only want these with errors
if (!f.error) {
return
}
const testName = `${JSON.stringify(f.test_json)}\n\tis invalid ` +
`because: ${f.error}`
it(testName, () => {
expect(() => {
Amount.from(f.test_json)
JSON.stringify(f.test_json)
}).toThrow()
})
})
}
describe('Amount', function () {
it('can be parsed from', function () {
expect(Amount.from('1000000') instanceof Amount).toBe(true)
expect(Amount.from('1000000').valueString()).toEqual('1000000')
const fixture = {
value: '1',
issuer: '0000000000000000000000000000000000000000',
currency: 'USD'
}
const amt = Amount.from(fixture)
const rewritten = {
value: '1',
issuer: 'rrrrrrrrrrrrrrrrrrrrrhoLvTp',
currency: 'USD'
}
expect(amt.toJSON()).toEqual(rewritten)
})
amountErrorTests()
})

View File

@@ -1,43 +0,0 @@
const assert = require('assert');
const fixtures = require('./fixtures/codec-fixtures.json');
const {decode, encode, decodeLedgerData} = require('../src');
function json(object) {
return JSON.stringify(object);
}
function truncateForDisplay(longStr) {
return longStr.slice(0, 10) + '...' + longStr.slice(-10);
}
describe('ripple-binary-codec', function() {
function makeSuite(name, entries) {
describe(name, function() {
entries.forEach((t, test_n) => {
// eslint-disable-next-line max-len
it(`${name}[${test_n}] can encode ${truncateForDisplay(json(t.json))} to ${truncateForDisplay(t.binary)}`,
() => {
assert.equal(t.binary, encode(t.json));
});
// eslint-disable-next-line max-len
it(`${name}[${test_n}] can decode ${truncateForDisplay(t.binary)} to ${truncateForDisplay(json(t.json))}`,
() => {
const decoded = decode(t.binary);
assert.deepEqual(t.json, decoded);
});
});
});
}
makeSuite('transactions', fixtures.transactions);
makeSuite('accountState', fixtures.accountState);
describe('ledgerData', function() {
fixtures.ledgerData.forEach((t, test_n) => {
it(`ledgerData[${test_n}] can decode ${t.binary} to ${json(t.json)}`,
() => {
const decoded = decodeLedgerData(t.binary);
assert.deepEqual(t.json, decoded);
});
});
})
});

View File

@@ -0,0 +1,44 @@
const fixtures = require('./fixtures/codec-fixtures.json')
const { decode, encode, decodeLedgerData } = require('../dist')
function json (object) {
return JSON.stringify(object)
}
function truncateForDisplay (longStr) {
return longStr.slice(0, 10) + '...' + longStr.slice(-10)
}
describe('ripple-binary-codec', function () {
function makeSuite (name, entries) {
describe(name, function () {
entries.forEach((t, testN) => {
// eslint-disable-next-line max-len
test(`${name}[${testN}] can encode ${truncateForDisplay(json(t.json))} to ${truncateForDisplay(t.binary)}`,
() => {
expect(t.binary).toEqual(encode(t.json))
})
// eslint-disable-next-line max-len
test(`${name}[${testN}] can decode ${truncateForDisplay(t.binary)} to ${truncateForDisplay(json(t.json))}`,
() => {
const decoded = decode(t.binary)
expect(t.json).toEqual(decoded)
})
})
})
}
makeSuite('transactions', fixtures.transactions)
makeSuite('accountState', fixtures.accountState)
describe('ledgerData', function () {
if (fixtures.ledgerData) {
fixtures.ledgerData.forEach((t, testN) => {
test(`ledgerData[${testN}] can decode ${t.binary} to ${json(t.json)}`,
() => {
const decoded = decodeLedgerData(t.binary)
expect(t.json).toEqual(decoded)
})
})
}
})
})

View File

@@ -1,341 +0,0 @@
/* eslint-disable func-style */
const coreTypes = require('../src/coretypes');
const _ = require('lodash');
const assert = require('assert');
const {encodeAccountID} = require('ripple-address-codec');
const {binary: {makeParser, readJSON}, Field, Amount, Hash160} = coreTypes;
const {enums: {TransactionType}} = coreTypes;
const utils = require('./utils');
const {parseHexOnly, assertEqualAmountJSON, hexOnly, loadFixture} = utils;
const {bytesToHex} = require('../src/utils/bytes-utils');
const fixtures = loadFixture('data-driven-tests.json');
const {BytesList} = require('../src/serdes/binary-serializer');
const __ = hexOnly;
function unused() {}
function toJSON(v) {
return v.toJSON ? v.toJSON() : v;
}
function basicApiTests() {
const bytes = parseHexOnly('00,01020304,0506', Uint8Array);
it('can read slices of bytes', () => {
const parser = makeParser(bytes);
assert.deepEqual(parser.pos(), 0);
assert(parser._buf instanceof Uint8Array);
const read1 = parser.read(1);
assert(read1 instanceof Uint8Array);
assert.deepEqual(read1, Uint8Array.from([0]));
assert.deepEqual(parser.read(4), Uint8Array.from([1, 2, 3, 4]));
assert.deepEqual(parser.read(2), Uint8Array.from([5, 6]));
assert.throws(() => parser.read(1));
});
it('can read a Uint32 at full', () => {
const parser = makeParser('FFFFFFFF');
assert.equal(parser.readUInt32(), 0xFFFFFFFF);
});
}
function transactionParsingTests() {
const transaction = {
json: {
'Account': 'raD5qJMAShLeHZXf9wjUmo6vRK4arj9cF3',
'Fee': '10',
'Flags': 0,
'Sequence': 103929,
'SigningPubKey':
'028472865AF4CB32AA285834B57576B7290AA8C31B459047DB27E16F418D6A7166',
'TakerGets': {'currency': 'ILS',
'issuer': 'rNPRNzBB92BVpAhhZr4iXDTveCgV5Pofm9',
'value': '1694.768'},
'TakerPays': '98957503520',
'TransactionType': 'OfferCreate',
'TxnSignature': __(`
304502202ABE08D5E78D1E74A4C18F2714F64E87B8BD57444AF
A5733109EB3C077077520022100DB335EE97386E4C0591CAC02
4D50E9230D8F171EEB901B5E5E4BD6D1E0AEF98C`)
},
binary: __(`
120007220000000024000195F964400000170A53AC2065D5460561E
C9DE000000000000000000000000000494C53000000000092D70596
8936C419CE614BF264B5EEB1CEA47FF468400000000000000A73210
28472865AF4CB32AA285834B57576B7290AA8C31B459047DB27E16F
418D6A71667447304502202ABE08D5E78D1E74A4C18F2714F64E87B
8BD57444AFA5733109EB3C077077520022100DB335EE97386E4C059
1CAC024D50E9230D8F171EEB901B5E5E4BD6D1E0AEF98C811439408
A69F0895E62149CFCC006FB89FA7D1E6E5D`)
};
const tx_json = transaction.json;
// These tests are basically development logs
it('can be done with low level apis', () => {
const parser = makeParser(transaction.binary);
assert.equal(parser.readField(), Field.TransactionType);
assert.equal(parser.readUInt16(), 7);
assert.equal(parser.readField(), Field.Flags);
assert.equal(parser.readUInt32(), 0);
assert.equal(parser.readField(), Field.Sequence);
assert.equal(parser.readUInt32(), 103929);
assert.equal(parser.readField(), Field.TakerPays);
parser.read(8);
assert.equal(parser.readField(), Field.TakerGets);
// amount value
assert(parser.read(8));
// amount currency
assert(Hash160.fromParser(parser));
assert.equal(encodeAccountID(parser.read(20)),
tx_json.TakerGets.issuer);
assert.equal(parser.readField(), Field.Fee);
assert(parser.read(8));
assert.equal(parser.readField(), Field.SigningPubKey);
assert.equal(parser.readVLLength(), 33);
assert.equal(bytesToHex(parser.read(33)), tx_json.SigningPubKey);
assert.equal(parser.readField(), Field.TxnSignature);
assert.equal(bytesToHex(parser.readVL()), tx_json.TxnSignature);
assert.equal(parser.readField(), Field.Account);
assert.equal(encodeAccountID(parser.readVL()), tx_json.Account);
assert(parser.end());
});
it('can be done with high level apis', () => {
const parser = makeParser(transaction.binary);
function readField() {
return parser.readFieldAndValue();
}
{
const [field, value] = readField();
assert.equal(field, Field.TransactionType);
assert.equal(value, TransactionType.OfferCreate);
}
{
const [field, value] = readField();
assert.equal(field, Field.Flags);
assert.equal(value, 0);
}
{
const [field, value] = readField();
assert.equal(field, Field.Sequence);
assert.equal(value, 103929);
}
{
const [field, value] = readField();
assert.equal(field, Field.TakerPays);
assert.equal(value.currency.isNative(), true);
assert.equal(value.currency.toJSON(), 'XRP');
}
{
const [field, value] = readField();
assert.equal(field, Field.TakerGets);
assert.equal(value.currency.isNative(), false);
assert.equal(value.issuer.toJSON(), tx_json.TakerGets.issuer);
}
{
const [field, value] = readField();
assert.equal(field, Field.Fee);
assert.equal(value.currency.isNative(), true);
}
{
const [field, value] = readField();
assert.equal(field, Field.SigningPubKey);
assert.equal(value.toJSON(), tx_json.SigningPubKey);
}
{
const [field, value] = readField();
assert.equal(field, Field.TxnSignature);
assert.equal(value.toJSON(), tx_json.TxnSignature);
}
{
const [field, value] = readField();
assert.equal(field, Field.Account);
assert.equal(value.toJSON(), tx_json.Account);
}
assert(parser.end());
});
it('can be done with higher level apis', () => {
const parser = makeParser(transaction.binary);
const jsonFromBinary = readJSON(parser);
assert.deepEqual(jsonFromBinary, tx_json);
});
it('readJSON (binary.decode) does not return STObject ', () => {
const parser = makeParser(transaction.binary);
const jsonFromBinary = readJSON(parser);
assert((jsonFromBinary instanceof coreTypes.STObject) === false);
assert(_.isPlainObject(jsonFromBinary));
});
}
function amountParsingTests() {
_.filter(fixtures.values_tests, {type: 'Amount'}).forEach((f, i) => {
if (f.error) {
return;
}
const parser = makeParser(f.expected_hex);
const testName =
`values_tests[${i}] parses ${f.expected_hex.slice(0, 16)}...
as ${JSON.stringify(f.test_json)}`;
it(testName, () => {
const value = parser.readType(Amount);
// May not actually be in canonical form. The fixtures are to be used
// also for json -> binary;
assertEqualAmountJSON(toJSON(value), f.test_json);
if (f.exponent) {
assert.equal(value.exponent(), f.exponent);
}
});
});
}
function fieldParsingTests() {
fixtures.fields_tests.forEach((f, i) => {
const parser = makeParser(f.expected_hex);
it(`fields[${i}]: parses ${f.expected_hex} as ${f.name}`, () => {
const field = parser.readField();
assert.equal(field.name, f.name);
assert.equal(field.type.name, f.type_name);
});
});
}
function assertRecyclable(json, forField) {
const Type = forField.associatedType;
const recycled = Type.from(json).toJSON();
assert.deepEqual(recycled, json);
const sink = new BytesList();
Type.from(recycled).toBytesSink(sink);
const recycledAgain = makeParser(sink.toHex())
.readType(Type)
.toJSON();
assert.deepEqual(recycledAgain, json);
}
function nestedObjectTests() {
function disabled(i) {
unused(i);
return false; // !_.includes([2], i);
}
fixtures.whole_objects.forEach((f, i) => {
if (disabled(i)) {
return;
}
it(`whole_objects[${i}]: can parse blob into
${JSON.stringify(f.tx_json)}`,
/* */ () => {
const parser = makeParser(f.blob_with_no_signing);
let ix = 0;
while (!parser.end()) {
const [field, value] = parser.readFieldAndValue();
const expected = f.fields[ix];
const expectedJSON = expected[1].json;
const expectedField = expected[0];
const actual = toJSON(value);
try {
assert.deepEqual(actual, expectedJSON);
} catch (e) {
throw new Error(`${e} ${field} a: ${actual} e: ${expectedJSON}`);
}
assert.equal(field.name, expectedField);
assertRecyclable(actual, field);
ix++;
}
});
});
}
function pathSetBinaryTests() {
const bytes = __(
`1200002200000000240000002E2E00004BF161D4C71AFD498D00000000000000
0000000000000055534400000000000A20B3C85F482532A9578DBB3950B85CA0
6594D168400000000000000A69D446F8038585E9400000000000000000000000
00425443000000000078CA21A6014541AB7B26C3929B9E0CD8C284D61C732103
A4665B1F0B7AE2BCA12E2DB80A192125BBEA660F80E9CEE137BA444C1B0769EC
7447304502205A964536805E35785C659D1F9670D057749AE39668175D6AA75D
25B218FE682E0221009252C0E5DDD5F2712A48F211669DE17B54113918E0D2C2
66F818095E9339D7D3811478CA21A6014541AB7B26C3929B9E0CD8C284D61C83
140A20B3C85F482532A9578DBB3950B85CA06594D1011231585E1F3BD02A15D6
185F8BB9B57CC60DEDDB37C10000000000000000000000004254430000000000
585E1F3BD02A15D6185F8BB9B57CC60DEDDB37C131E4FE687C90257D3D2D694C
8531CDEECBE84F33670000000000000000000000004254430000000000E4FE68
7C90257D3D2D694C8531CDEECBE84F3367310A20B3C85F482532A9578DBB3950
B85CA06594D100000000000000000000000042544300000000000A20B3C85F48
2532A9578DBB3950B85CA06594D1300000000000000000000000005553440000
0000000A20B3C85F482532A9578DBB3950B85CA06594D1FF31585E1F3BD02A15
D6185F8BB9B57CC60DEDDB37C100000000000000000000000042544300000000
00585E1F3BD02A15D6185F8BB9B57CC60DEDDB37C131E4FE687C90257D3D2D69
4C8531CDEECBE84F33670000000000000000000000004254430000000000E4FE
687C90257D3D2D694C8531CDEECBE84F33673115036E2D3F5437A83E5AC3CAEE
34FF2C21DEB618000000000000000000000000425443000000000015036E2D3F
5437A83E5AC3CAEE34FF2C21DEB6183000000000000000000000000055534400
000000000A20B3C85F482532A9578DBB3950B85CA06594D1FF31585E1F3BD02A
15D6185F8BB9B57CC60DEDDB37C1000000000000000000000000425443000000
0000585E1F3BD02A15D6185F8BB9B57CC60DEDDB37C13157180C769B66D942EE
69E6DCC940CA48D82337AD000000000000000000000000425443000000000057
180C769B66D942EE69E6DCC940CA48D82337AD10000000000000000000000000
58525000000000003000000000000000000000000055534400000000000A20B3
C85F482532A9578DBB3950B85CA06594D100`);
const expectedJSON =
[[{account: 'r9hEDb4xBGRfBCcX3E4FirDWQBAYtpxC8K',
currency: 'BTC',
issuer: 'r9hEDb4xBGRfBCcX3E4FirDWQBAYtpxC8K'},
{account: 'rM1oqKtfh1zgjdAgbFmaRm3btfGBX25xVo',
currency: 'BTC',
issuer: 'rM1oqKtfh1zgjdAgbFmaRm3btfGBX25xVo'},
{account: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B',
currency: 'BTC',
issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B'},
{currency: 'USD',
issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B'}],
[{account: 'r9hEDb4xBGRfBCcX3E4FirDWQBAYtpxC8K',
currency: 'BTC',
issuer: 'r9hEDb4xBGRfBCcX3E4FirDWQBAYtpxC8K'},
{account: 'rM1oqKtfh1zgjdAgbFmaRm3btfGBX25xVo',
currency: 'BTC',
issuer: 'rM1oqKtfh1zgjdAgbFmaRm3btfGBX25xVo'},
{account: 'rpvfJ4mR6QQAeogpXEKnuyGBx8mYCSnYZi',
currency: 'BTC',
issuer: 'rpvfJ4mR6QQAeogpXEKnuyGBx8mYCSnYZi'},
{currency: 'USD',
issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B'}],
[{account: 'r9hEDb4xBGRfBCcX3E4FirDWQBAYtpxC8K',
currency: 'BTC',
issuer: 'r9hEDb4xBGRfBCcX3E4FirDWQBAYtpxC8K'},
{account: 'r3AWbdp2jQLXLywJypdoNwVSvr81xs3uhn',
currency: 'BTC',
issuer: 'r3AWbdp2jQLXLywJypdoNwVSvr81xs3uhn'},
{currency: '0000000000000000000000005852500000000000'},
{currency: 'USD',
issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B'}]];
it('works with long paths', () => {
const parser = makeParser(bytes);
const txn = readJSON(parser);
assert.deepEqual(txn.Paths, expectedJSON);
// TODO: this should go elsewhere
assert.deepEqual(
coreTypes.PathSet.from(txn.Paths).toJSON(),
expectedJSON
);
});
}
describe('BinaryParser', function() {
function dataDrivenTests() {
describe('Amount parsing tests', amountParsingTests);
describe('Field Tests', fieldParsingTests);
describe('Parsing nested objects', nestedObjectTests);
}
describe('pathSetBinaryTests', pathSetBinaryTests);
describe('Basic API', basicApiTests);
describe('Parsing a transaction', transactionParsingTests);
describe('Data Driven Tests', dataDrivenTests);
});

View File

@@ -0,0 +1,377 @@
/* eslint-disable func-style */
const { coreTypes } = require('../dist/types')
const Decimal = require('decimal.js')
const _ = require('lodash')
const { encodeAccountID } = require('ripple-address-codec')
const { binary } = require('../dist/coretypes')
const { Amount, Hash160 } = coreTypes
const { makeParser, readJSON } = binary
const { Enums } = require('./../dist/enums')
const Field = Enums.Field
const { TransactionType } = Enums
const { parseHexOnly, hexOnly, loadFixture } = require('./utils')
const { bytesToHex } = require('../dist/utils/bytes-utils')
const fixtures = loadFixture('data-driven-tests.json')
const { BytesList } = require('../dist/serdes/binary-serializer')
const __ = hexOnly
function unused () {}
function toJSON (v) {
return v.toJSON ? v.toJSON() : v
}
function assertEqualAmountJSON (actual, expected) {
expect((typeof actual) === (typeof expected)).toBe(true)
if ((typeof actual) === 'string') {
expect(actual).toEqual(expected)
return
}
expect(actual.currency).toEqual(expected.currency)
expect(actual.issuer).toEqual(expected.issuer)
expect(actual.value === expected.value ||
new Decimal(actual.value).equals(
new Decimal(expected.value))).toBe(true)
}
function basicApiTests () {
const bytes = parseHexOnly('00,01020304,0506', Uint8Array)
test('can read slices of bytes', () => {
const parser = makeParser(bytes)
expect(parser.pos()).toBe(0)
expect(parser._buf instanceof Uint8Array).toBe(true)
const read1 = parser.read(1)
expect(read1 instanceof Uint8Array).toBe(true)
expect(read1).toEqual(Uint8Array.from([0]))
expect(parser.read(4)).toEqual(Uint8Array.from([1, 2, 3, 4]))
expect(parser.read(2)).toEqual(Uint8Array.from([5, 6]))
expect(() => parser.read(1)).toThrow()
})
test('can read a Uint32 at full', () => {
const parser = makeParser('FFFFFFFF')
expect(parser.readUInt32()).toEqual(0xFFFFFFFF)
})
}
basicApiTests()
function transactionParsingTests () {
const transaction = {
json: {
Account: 'raD5qJMAShLeHZXf9wjUmo6vRK4arj9cF3',
Fee: '10',
Flags: 0,
Sequence: 103929,
SigningPubKey:
'028472865AF4CB32AA285834B57576B7290AA8C31B459047DB27E16F418D6A7166',
TakerGets: {
currency: 'ILS',
issuer: 'rNPRNzBB92BVpAhhZr4iXDTveCgV5Pofm9',
value: '1694.768'
},
TakerPays: '98957503520',
TransactionType: 'OfferCreate',
TxnSignature: __(`
304502202ABE08D5E78D1E74A4C18F2714F64E87B8BD57444AF
A5733109EB3C077077520022100DB335EE97386E4C0591CAC02
4D50E9230D8F171EEB901B5E5E4BD6D1E0AEF98C`)
},
binary: __(`
120007220000000024000195F964400000170A53AC2065D5460561E
C9DE000000000000000000000000000494C53000000000092D70596
8936C419CE614BF264B5EEB1CEA47FF468400000000000000A73210
28472865AF4CB32AA285834B57576B7290AA8C31B459047DB27E16F
418D6A71667447304502202ABE08D5E78D1E74A4C18F2714F64E87B
8BD57444AFA5733109EB3C077077520022100DB335EE97386E4C059
1CAC024D50E9230D8F171EEB901B5E5E4BD6D1E0AEF98C811439408
A69F0895E62149CFCC006FB89FA7D1E6E5D`)
}
const tx_json = transaction.json
// These tests are basically development logs
test('can be done with low level apis', () => {
const parser = makeParser(transaction.binary)
expect(parser.readField()).toEqual(Field.TransactionType)
expect(parser.readUInt16()).toEqual(7)
expect(parser.readField()).toEqual(Field.Flags)
expect(parser.readUInt32()).toEqual(0)
expect(parser.readField()).toEqual(Field.Sequence)
expect(parser.readUInt32()).toEqual(103929)
expect(parser.readField()).toEqual(Field.TakerPays)
parser.read(8)
expect(parser.readField()).toEqual(Field.TakerGets)
// amount value
expect(parser.read(8)).not.toBe([])
// amount currency
expect(Hash160.fromParser(parser)).not.toBe([])
expect(encodeAccountID(parser.read(20))).toEqual(tx_json.TakerGets.issuer)
expect(parser.readField()).toEqual(Field.Fee)
expect(parser.read(8)).not.toEqual([])
expect(parser.readField()).toEqual(Field.SigningPubKey)
expect(parser.readVLLength()).toBe(33)
expect(bytesToHex(parser.read(33))).toEqual(tx_json.SigningPubKey)
expect(parser.readField()).toEqual(Field.TxnSignature)
expect(bytesToHex(parser.readVL())).toEqual(tx_json.TxnSignature)
expect(parser.readField()).toEqual(Field.Account)
expect(encodeAccountID(parser.readVL())).toEqual(tx_json.Account)
expect(parser.end()).toBe(true)
})
test('can be done with high level apis', () => {
const parser = makeParser(transaction.binary)
function readField () {
return parser.readFieldAndValue()
}
{
const [field, value] = readField()
expect(field).toEqual(Field.TransactionType)
expect(value).toEqual(TransactionType.OfferCreate)
}
{
const [field, value] = readField()
expect(field).toEqual(Field.Flags)
expect(value.val).toEqual(0)
}
{
const [field, value] = readField()
expect(field).toEqual(Field.Sequence)
expect(value.val).toEqual(103929)
}
{
const [field, value] = readField()
expect(field).toEqual(Field.TakerPays)
expect(value.currency.isNative()).toEqual(true)
expect(value.currency.toJSON()).toEqual('XRP')
}
{
const [field, value] = readField()
expect(field).toEqual(Field.TakerGets)
expect(value.currency.isNative()).toEqual(false)
expect(value.issuer.toJSON()).toEqual(tx_json.TakerGets.issuer)
}
{
const [field, value] = readField()
expect(field).toEqual(Field.Fee)
expect(value.currency.isNative()).toEqual(true)
}
{
const [field, value] = readField()
expect(field).toEqual(Field.SigningPubKey)
expect(value.toJSON()).toEqual(tx_json.SigningPubKey)
}
{
const [field, value] = readField()
expect(field).toEqual(Field.TxnSignature)
expect(value.toJSON()).toEqual(tx_json.TxnSignature)
}
{
const [field, value] = readField()
expect(field).toEqual(Field.Account)
expect(value.toJSON()).toEqual(tx_json.Account)
}
expect(parser.end()).toBe(true)
})
test('can be done with higher level apis', () => {
const parser = makeParser(transaction.binary)
const jsonFromBinary = readJSON(parser)
expect(jsonFromBinary).toEqual(tx_json)
})
test('readJSON (binary.decode) does not return STObject ', () => {
const parser = makeParser(transaction.binary)
const jsonFromBinary = readJSON(parser)
expect(jsonFromBinary instanceof coreTypes.STObject).toBe(false)
expect(_.isPlainObject(jsonFromBinary)).toBe(true)
})
}
transactionParsingTests()
function amountParsingTests () {
_.filter(fixtures.values_tests, { type: 'Amount' }).forEach((f, i) => {
if (f.error) {
return
}
const parser = makeParser(f.expected_hex)
const testName =
`values_tests[${i}] parses ${f.expected_hex.slice(0, 16)}...
as ${JSON.stringify(f.test_json)}`
test(testName, () => {
const value = parser.readType(Amount)
// May not actually be in canonical form. The fixtures are to be used
// also for json -> binary;
assertEqualAmountJSON(toJSON(value), (f.test_json))
if (f.exponent) {
expect(value.exponent()).toEqual(f.exponent)
}
})
})
}
amountParsingTests()
function fieldParsingTests () {
fixtures.fields_tests.forEach((f, i) => {
const parser = makeParser(f.expected_hex)
test(`fields[${i}]: parses ${f.expected_hex} as ${f.name}`, () => {
const field = parser.readField()
expect(field.name).toEqual(f.name)
expect(field.type.name).toEqual(f.type_name)
})
})
}
fieldParsingTests()
function assertRecyclable (json, forField) {
const Type = forField.associatedType
const recycled = Type.from(json).toJSON()
expect(recycled).toEqual(json)
const sink = new BytesList()
Type.from(recycled).toBytesSink(sink)
const recycledAgain = makeParser(sink.toHex())
.readType(Type)
.toJSON()
expect(recycledAgain).toEqual(json)
}
function nestedObjectTests () {
function disabled (i) {
unused(i)
return false // !_.includes([2], i);
}
fixtures.whole_objects.forEach((f, i) => {
if (disabled(i)) {
return
}
test(`whole_objects[${i}]: can parse blob into
${JSON.stringify(f.tx_json)}`,
/* */ () => {
const parser = makeParser(f.blob_with_no_signing)
let ix = 0
while (!parser.end()) {
const [field, value] = parser.readFieldAndValue()
const expected = f.fields[ix]
const expectedJSON = expected[1].json
const expectedField = expected[0]
const actual = toJSON(value)
try {
expect(actual).toEqual(expectedJSON)
} catch (e) {
throw new Error(`${e} ${field} a: ${actual} e: ${expectedJSON}`)
}
expect(field.name).toEqual(expectedField)
assertRecyclable(actual, field)
ix++
}
})
})
}
function pathSetBinaryTests () {
const bytes = __(
`1200002200000000240000002E2E00004BF161D4C71AFD498D00000000000000
0000000000000055534400000000000A20B3C85F482532A9578DBB3950B85CA0
6594D168400000000000000A69D446F8038585E9400000000000000000000000
00425443000000000078CA21A6014541AB7B26C3929B9E0CD8C284D61C732103
A4665B1F0B7AE2BCA12E2DB80A192125BBEA660F80E9CEE137BA444C1B0769EC
7447304502205A964536805E35785C659D1F9670D057749AE39668175D6AA75D
25B218FE682E0221009252C0E5DDD5F2712A48F211669DE17B54113918E0D2C2
66F818095E9339D7D3811478CA21A6014541AB7B26C3929B9E0CD8C284D61C83
140A20B3C85F482532A9578DBB3950B85CA06594D1011231585E1F3BD02A15D6
185F8BB9B57CC60DEDDB37C10000000000000000000000004254430000000000
585E1F3BD02A15D6185F8BB9B57CC60DEDDB37C131E4FE687C90257D3D2D694C
8531CDEECBE84F33670000000000000000000000004254430000000000E4FE68
7C90257D3D2D694C8531CDEECBE84F3367310A20B3C85F482532A9578DBB3950
B85CA06594D100000000000000000000000042544300000000000A20B3C85F48
2532A9578DBB3950B85CA06594D1300000000000000000000000005553440000
0000000A20B3C85F482532A9578DBB3950B85CA06594D1FF31585E1F3BD02A15
D6185F8BB9B57CC60DEDDB37C100000000000000000000000042544300000000
00585E1F3BD02A15D6185F8BB9B57CC60DEDDB37C131E4FE687C90257D3D2D69
4C8531CDEECBE84F33670000000000000000000000004254430000000000E4FE
687C90257D3D2D694C8531CDEECBE84F33673115036E2D3F5437A83E5AC3CAEE
34FF2C21DEB618000000000000000000000000425443000000000015036E2D3F
5437A83E5AC3CAEE34FF2C21DEB6183000000000000000000000000055534400
000000000A20B3C85F482532A9578DBB3950B85CA06594D1FF31585E1F3BD02A
15D6185F8BB9B57CC60DEDDB37C1000000000000000000000000425443000000
0000585E1F3BD02A15D6185F8BB9B57CC60DEDDB37C13157180C769B66D942EE
69E6DCC940CA48D82337AD000000000000000000000000425443000000000057
180C769B66D942EE69E6DCC940CA48D82337AD10000000000000000000000000
58525000000000003000000000000000000000000055534400000000000A20B3
C85F482532A9578DBB3950B85CA06594D100`)
const expectedJSON =
[[{
account: 'r9hEDb4xBGRfBCcX3E4FirDWQBAYtpxC8K',
currency: 'BTC',
issuer: 'r9hEDb4xBGRfBCcX3E4FirDWQBAYtpxC8K'
},
{
account: 'rM1oqKtfh1zgjdAgbFmaRm3btfGBX25xVo',
currency: 'BTC',
issuer: 'rM1oqKtfh1zgjdAgbFmaRm3btfGBX25xVo'
},
{
account: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B',
currency: 'BTC',
issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B'
},
{
currency: 'USD',
issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B'
}],
[{
account: 'r9hEDb4xBGRfBCcX3E4FirDWQBAYtpxC8K',
currency: 'BTC',
issuer: 'r9hEDb4xBGRfBCcX3E4FirDWQBAYtpxC8K'
},
{
account: 'rM1oqKtfh1zgjdAgbFmaRm3btfGBX25xVo',
currency: 'BTC',
issuer: 'rM1oqKtfh1zgjdAgbFmaRm3btfGBX25xVo'
},
{
account: 'rpvfJ4mR6QQAeogpXEKnuyGBx8mYCSnYZi',
currency: 'BTC',
issuer: 'rpvfJ4mR6QQAeogpXEKnuyGBx8mYCSnYZi'
},
{
currency: 'USD',
issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B'
}],
[{
account: 'r9hEDb4xBGRfBCcX3E4FirDWQBAYtpxC8K',
currency: 'BTC',
issuer: 'r9hEDb4xBGRfBCcX3E4FirDWQBAYtpxC8K'
},
{
account: 'r3AWbdp2jQLXLywJypdoNwVSvr81xs3uhn',
currency: 'BTC',
issuer: 'r3AWbdp2jQLXLywJypdoNwVSvr81xs3uhn'
},
{ currency: '0000000000000000000000005852500000000000' },
{
currency: 'USD',
issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B'
}]]
test('works with long paths', () => {
const parser = makeParser(bytes)
const txn = readJSON(parser)
expect(txn.Paths).toEqual(expectedJSON)
// TODO: this should go elsewhere
expect(
coreTypes.PathSet.from(txn.Paths).toJSON()).toEqual(
expectedJSON
)
})
}
pathSetBinaryTests()
describe('Binary Parser', function() {
describe('pathSetBinaryTests', pathSetBinaryTests);
describe('nestedObjectTests', nestedObjectTests);
});

View File

@@ -1,194 +0,0 @@
/* eslint-disable func-style */
const BN = require('bn.js');
const assert = require('assert');
const lib = require('../src/coretypes');
const encode = require('../src').encode;
const {binary: {makeParser, BytesList, BinarySerializer}} = lib;
const {UInt8, UInt16, UInt32, UInt64, STObject} = lib;
const {loadFixture} = require('./utils');
const fixtures = loadFixture('data-driven-tests.json');
const deliverMinTx = require('./fixtures/delivermin-tx.json');
const deliverMinTxBinary = require('./fixtures/delivermin-tx-binary.json');
const SignerListSet = {
tx: require('./fixtures/signerlistset-tx.json'),
binary: require('./fixtures/signerlistset-tx-binary.json'),
meta: require('./fixtures/signerlistset-tx-meta-binary.json')
};
const DepositPreauth = {
tx: require('./fixtures/deposit-preauth-tx.json'),
binary: require('./fixtures/deposit-preauth-tx-binary.json'),
meta: require('./fixtures/deposit-preauth-tx-meta-binary.json')
};
const Escrow = {
create: {
tx: require('./fixtures/escrow-create-tx.json'),
binary: require('./fixtures/escrow-create-binary.json')
},
finish: {
tx: require('./fixtures/escrow-finish-tx.json'),
binary: require('./fixtures/escrow-finish-binary.json'),
meta: require('./fixtures/escrow-finish-meta-binary.json')
},
cancel: {
tx: require('./fixtures/escrow-cancel-tx.json'),
binary: require('./fixtures/escrow-cancel-binary.json')
}
}
const PaymentChannel = {
create: {
tx: require('./fixtures/payment-channel-create-tx.json'),
binary: require('./fixtures/payment-channel-create-binary.json')
},
fund: {
tx: require('./fixtures/payment-channel-fund-tx.json'),
binary: require('./fixtures/payment-channel-fund-binary.json')
},
claim: {
tx: require('./fixtures/payment-channel-claim-tx.json'),
binary: require('./fixtures/payment-channel-claim-binary.json')
}
}
function bytesListTest() {
const list = new BytesList().put([0]).put([2, 3]).put([4, 5]);
it('is an Array<Uint8Array>', function() {
assert(Array.isArray(list.arrays));
assert(list.arrays[0] instanceof Uint8Array);
});
it('keeps track of the length itself', function() {
assert.equal(list.length, 5);
});
it('can join all arrays into one via toBytes', function() {
const joined = list.toBytes();
assert(joined.length, 5);
assert.deepEqual(joined, Uint8Array.from([0, 2, 3, 4, 5]));
});
}
function assertRecycles(blob) {
const parser = makeParser(blob);
const so = parser.readType(STObject);
const out = new BytesList();
so.toBytesSink(out);
const hex = out.toHex();
assert.equal(hex, blob);
assert.notEqual(hex + ':', blob);
}
function nestedObjectTests() {
fixtures.whole_objects.forEach((f, i) => {
it(`whole_objects[${i}]: can parse blob and dump out same blob`,
/* */ () => {
assertRecycles(f.blob_with_no_signing);
});
});
}
function UIntTest() {
function check(type, n, expected) {
it(`Uint${type.width * 8} serializes ${n} as ${expected}`, function() {
const bl = new BytesList();
const serializer = new BinarySerializer(bl);
if (expected === 'throws') {
assert.throws(() => serializer.writeType(type, n));
return;
}
serializer.writeType(type, n);
assert.deepEqual(bl.toBytes(), Uint8Array.from(expected));
});
}
check(UInt8, 5, [5]);
check(UInt16, 5, [0, 5]);
check(UInt32, 5, [0, 0, 0, 5]);
check(UInt32, 0xFFFFFFFF, [255, 255, 255, 255]);
check(UInt8, 0xFEFFFFFF, 'throws');
check(UInt16, 0xFEFFFFFF, 'throws');
check(UInt16, 0xFEFFFFFF, 'throws');
check(UInt64, 0xFEFFFFFF, [0, 0, 0, 0, 254, 255, 255, 255]);
check(UInt64, -1, 'throws');
check(UInt64, 0, [0, 0, 0, 0, 0, 0, 0, 0]);
check(UInt64, 1, [0, 0, 0, 0, 0, 0, 0, 1]);
check(UInt64, new BN(1), [0, 0, 0, 0, 0, 0, 0, 1]);
}
function parseLedger4320278() {
it('can parse object', done => {
this.timeout(30e3);
const json = loadFixture('as-ledger-4320278.json');
json.forEach(e => {
assertRecycles(e.binary);
});
done();
});
}
function deliverMinTest() {
it('can serialize DeliverMin', () => {
assert.strictEqual(encode(deliverMinTx), deliverMinTxBinary);
});
}
function SignerListSetTest() {
it('can serialize SignerListSet', () => {
assert.strictEqual(encode(SignerListSet.tx), SignerListSet.binary);
});
it('can serialize SignerListSet metadata', () => {
assert.strictEqual(encode(SignerListSet.tx.meta), SignerListSet.meta);
});
}
function DepositPreauthTest() {
it('can serialize DepositPreauth', () => {
assert.strictEqual(encode(DepositPreauth.tx), DepositPreauth.binary);
});
it('can serialize DepositPreauth metadata', () => {
assert.strictEqual(encode(DepositPreauth.tx.meta), DepositPreauth.meta);
});
}
function EscrowTest() {
it('can serialize EscrowCreate', () => {
assert.strictEqual(encode(Escrow.create.tx),
Escrow.create.binary);
});
it('can serialize EscrowFinish', () => {
assert.strictEqual(encode(Escrow.finish.tx),
Escrow.finish.binary);
assert.strictEqual(encode(Escrow.finish.tx.meta),
Escrow.finish.meta);
});
it('can serialize EscrowCancel', () => {
assert.strictEqual(encode(Escrow.cancel.tx),
Escrow.cancel.binary);
});
}
function PaymentChannelTest() {
it('can serialize PaymentChannelCreate', () => {
assert.strictEqual(encode(PaymentChannel.create.tx),
PaymentChannel.create.binary);
});
it('can serialize PaymentChannelFund', () => {
assert.strictEqual(encode(PaymentChannel.fund.tx),
PaymentChannel.fund.binary);
});
it('can serialize PaymentChannelClaim', () => {
assert.strictEqual(encode(PaymentChannel.claim.tx),
PaymentChannel.claim.binary);
});
}
describe('Binary Serialization', function() {
describe.skip('parseLedger4320278', parseLedger4320278);
describe('nestedObjectTests', nestedObjectTests);
describe('UIntTest', UIntTest);
describe('BytesList', bytesListTest);
describe('DeliverMin', deliverMinTest);
describe('DepositPreauth', DepositPreauthTest);
describe('SignerListSet', SignerListSetTest);
describe('Escrow', EscrowTest);
describe('PaymentChannel', PaymentChannelTest);
});

View File

@@ -0,0 +1,183 @@
/* eslint-disable func-style */
const { BN } = require('bn.js')
const { binary } = require('../dist/coretypes')
const { encode } = require('../dist')
const { makeParser, BytesList, BinarySerializer } = binary
const { coreTypes } = require('../dist/types')
const { UInt8, UInt16, UInt32, UInt64, STObject } = coreTypes
const { loadFixture } = require('./utils')
const fixtures = loadFixture('data-driven-tests.json')
const deliverMinTx = require('./fixtures/delivermin-tx.json')
const deliverMinTxBinary = require('./fixtures/delivermin-tx-binary.json')
const SignerListSet = {
tx: require('./fixtures/signerlistset-tx.json'),
binary: require('./fixtures/signerlistset-tx-binary.json'),
meta: require('./fixtures/signerlistset-tx-meta-binary.json')
}
const DepositPreauth = {
tx: require('./fixtures/deposit-preauth-tx.json'),
binary: require('./fixtures/deposit-preauth-tx-binary.json'),
meta: require('./fixtures/deposit-preauth-tx-meta-binary.json')
}
const Escrow = {
create: {
tx: require('./fixtures/escrow-create-tx.json'),
binary: require('./fixtures/escrow-create-binary.json')
},
finish: {
tx: require('./fixtures/escrow-finish-tx.json'),
binary: require('./fixtures/escrow-finish-binary.json'),
meta: require('./fixtures/escrow-finish-meta-binary.json')
},
cancel: {
tx: require('./fixtures/escrow-cancel-tx.json'),
binary: require('./fixtures/escrow-cancel-binary.json')
}
}
const PaymentChannel = {
create: {
tx: require('./fixtures/payment-channel-create-tx.json'),
binary: require('./fixtures/payment-channel-create-binary.json')
},
fund: {
tx: require('./fixtures/payment-channel-fund-tx.json'),
binary: require('./fixtures/payment-channel-fund-binary.json')
},
claim: {
tx: require('./fixtures/payment-channel-claim-tx.json'),
binary: require('./fixtures/payment-channel-claim-binary.json')
}
}
function bytesListTest () {
const list = new BytesList().put([0]).put([2, 3]).put([4, 5])
test('is an Array<Uint8Array>', function () {
expect(Array.isArray(list.arrays)).toBe(true)
expect(list.arrays[0] instanceof Uint8Array).toBe(true)
})
test('keeps track of the length itself', function () {
expect(list).toHaveLength(5)
})
test('can join all arrays into one via toBytes', function () {
const joined = list.toBytes()
expect(joined).toHaveLength(5)
expect(joined).toEqual(Uint8Array.from([0, 2, 3, 4, 5]))
})
}
function assertRecycles (blob) {
const parser = makeParser(blob)
const so = parser.readType(STObject)
const out = new BytesList()
so.toBytesSink(out)
const hex = out.toHex()
expect(hex).toEqual(blob)
expect(hex + ':').not.toEqual(blob)
}
function nestedObjectTests () {
fixtures.whole_objects.forEach((f, i) => {
test(`whole_objects[${i}]: can parse blob and dump out same blob`,
/* */ () => {
assertRecycles(f.blob_with_no_signing)
})
})
}
function check (type, n, expected) {
test(`Uint${type.width * 8} serializes ${n} as ${expected}`, function () {
const bl = new BytesList()
const serializer = new BinarySerializer(bl)
if (expected === 'throws') {
expect(() => serializer.writeType(type, n)).toThrow()
return
}
serializer.writeType(type, n)
expect(bl.toBytes()).toEqual(Uint8Array.from(expected))
})
}
check(UInt8, 5, [5])
check(UInt16, 5, [0, 5])
check(UInt32, 5, [0, 0, 0, 5])
check(UInt32, 0xFFFFFFFF, [255, 255, 255, 255])
check(UInt8, 0xFEFFFFFF, 'throws')
check(UInt16, 0xFEFFFFFF, 'throws')
check(UInt16, 0xFEFFFFFF, 'throws')
check(UInt64, 0xFEFFFFFF, [0, 0, 0, 0, 254, 255, 255, 255])
check(UInt64, -1, 'throws')
check(UInt64, 0, [0, 0, 0, 0, 0, 0, 0, 0])
check(UInt64, 1, [0, 0, 0, 0, 0, 0, 0, 1])
check(UInt64, new BN(1), [0, 0, 0, 0, 0, 0, 0, 1])
// function parseLedger4320278() {
// test('can parse object', done => {
// const json = loadFixture('as-ledger-4320278.json');
// json.forEach(e => {
// assertRecycles(e.binary);
// });
// done();
// });
// }
// parseLedger4320278();
function deliverMinTest () {
test('can serialize DeliverMin', () => {
expect(encode(deliverMinTx)).toEqual(deliverMinTxBinary)
})
}
function SignerListSetTest () {
test('can serialize SignerListSet', () => {
expect(encode(SignerListSet.tx)).toEqual(SignerListSet.binary)
})
test('can serialize SignerListSet metadata', () => {
expect(encode(SignerListSet.tx.meta)).toEqual(SignerListSet.meta)
})
}
function DepositPreauthTest () {
test('can serialize DepositPreauth', () => {
expect(encode(DepositPreauth.tx)).toEqual(DepositPreauth.binary)
})
test('can serialize DepositPreauth metadata', () => {
expect(encode(DepositPreauth.tx.meta)).toEqual(DepositPreauth.meta)
})
}
function EscrowTest () {
test('can serialize EscrowCreate', () => {
expect(encode(Escrow.create.tx)).toEqual(Escrow.create.binary)
})
test('can serialize EscrowFinish', () => {
expect(encode(Escrow.finish.tx)).toEqual(Escrow.finish.binary)
expect(encode(Escrow.finish.tx.meta)).toEqual(Escrow.finish.meta)
})
test('can serialize EscrowCancel', () => {
expect(encode(Escrow.cancel.tx)).toEqual(Escrow.cancel.binary)
})
}
function PaymentChannelTest () {
test('can serialize PaymentChannelCreate', () => {
expect(encode(PaymentChannel.create.tx)).toEqual(PaymentChannel.create.binary)
})
test('can serialize PaymentChannelFund', () => {
expect(encode(PaymentChannel.fund.tx)).toEqual(PaymentChannel.fund.binary)
})
test('can serialize PaymentChannelClaim', () => {
expect(encode(PaymentChannel.claim.tx)).toEqual(PaymentChannel.claim.binary)
})
}
describe('Binary Serialization', function() {
describe('nestedObjectTests', nestedObjectTests);
describe('BytesList', bytesListTest);
describe('DeliverMin', deliverMinTest);
describe('DepositPreauth', DepositPreauthTest);
describe('SignerListSet', SignerListSetTest);
describe('Escrow', EscrowTest);
describe('PaymentChannel', PaymentChannelTest);
})

View File

@@ -1,72 +0,0 @@
const assert = require('assert');
const bytesUtils = require('../src/utils/bytes-utils');
const {slice, compareBytes, parseBytes, bytesToHex} = bytesUtils;
describe('bytes-utils', function() {
describe('parseBytes', function() {
it('can decode hex', function() {
assert.deepEqual(parseBytes('0012'), [0x00, 0x12]);
assert.deepEqual(parseBytes('0012'), [0x00, 0x12]);
assert.deepEqual(parseBytes('00AA'), [0x00, 0xaa]);
});
it('can decode hex to a Uint8Array', function() {
const result = parseBytes('0012', Uint8Array);
assert(result instanceof Uint8Array);
assert.deepEqual(result, Uint8Array.from([0x00, 0x12]));
});
it('can convert a list to a Uint8Array', function() {
const result = parseBytes([0x00, 0x12], Uint8Array);
assert(result instanceof Uint8Array);
assert.deepEqual(result, Uint8Array.from([0x00, 0x12]));
});
it('can decode hex to a Buffer', function() {
const result = parseBytes('0012', Buffer);
assert(result instanceof Buffer);
assert.deepEqual(result.toJSON().data, [0x00, 0x12]);
});
});
describe('bytesToHex', function() {
it('can encode an array as hex', function() {
assert.deepEqual(bytesToHex([0x00, 0xaa]), '00AA');
assert.deepEqual(bytesToHex([0xaa]), 'AA');
});
it('can encode Uint8Array as hex', function() {
assert.deepEqual(bytesToHex(new Uint8Array([0x00, 0xaa])), '00AA');
assert.deepEqual(bytesToHex(new Uint8Array([0xaa])), 'AA');
});
});
describe('compareBytes', function() {
it('compares the bytes sequence as big endian number', function() {
assert.equal(compareBytes([0, 1, 2], [1, 2, 3]), -1);
});
it('throws when the bytes sequences are of unlike length', function() {
assert.throws(() => compareBytes([0, 1], [1]));
});
});
describe('slice', function() {
const val = [1, 2, 3, 4, 5];
it('creates a slice of the same type as first arg', function() {
assert(Array.isArray(slice(val)));
});
it('the 2nd arg is the start position [2:]', function() {
assert.deepEqual(val.slice(2), [3, 4, 5]);
assert.deepEqual(slice(val, 2), [3, 4, 5]);
});
it('the 3rd arg is the end position [2:4]', function() {
assert.deepEqual(slice(val, 2, 4), [3, 4]);
});
it('can slice using negative numbers [-3:]', function() {
assert.deepEqual(slice(val, -3), [3, 4, 5]);
});
it('can slice using negative numbers [-3:-1]', function() {
assert.deepEqual(slice(val, -3, -1), [3, 4]);
});
it('the 4th arg is the output class type', function() {
assert.deepEqual(slice(val, 2, 4, Buffer).toJSON().data, [3, 4]);
assert.deepEqual(slice(val, 2, 4, Uint8Array), Uint8Array.from([3, 4]));
});
});
});

View File

@@ -0,0 +1,70 @@
const { slice, compareBytes, parseBytes, bytesToHex } = require('../dist/utils/bytes-utils')
describe('bytes-utils', function () {
describe('parseBytes', function () {
test('can decode hex', function () {
expect(parseBytes('0012')).toEqual([0x00, 0x12])
expect(parseBytes('0012')).toEqual([0x00, 0x12])
expect(parseBytes('00AA')).toEqual([0x00, 0xaa])
})
test('can decode hex to a Uint8Array', function () {
const result = parseBytes('0012', Uint8Array)
expect(result instanceof Uint8Array).toBe(true)
expect(result).toEqual(Uint8Array.from([0x00, 0x12]))
})
test('can convert a list to a Uint8Array', function () {
const result = parseBytes([0x00, 0x12], Uint8Array)
expect(result instanceof Uint8Array).toBe(true)
expect(result).toEqual(Uint8Array.from([0x00, 0x12]))
})
test('can decode hex to a Buffer', function () {
const result = parseBytes('0012', Buffer)
expect(result instanceof Buffer).toBe(true)
expect(result.toJSON().data).toEqual([0x00, 0x12])
})
})
describe('bytesToHex', function () {
test('can encode an array as hex', function () {
expect(bytesToHex([0x00, 0xaa])).toBe('00AA')
expect(bytesToHex([0xaa])).toBe('AA')
})
test('can encode Uint8Array as hex', function () {
expect(bytesToHex(new Uint8Array([0x00, 0xaa]))).toBe('00AA')
expect(bytesToHex(new Uint8Array([0xaa]))).toBe('AA')
})
})
describe('compareBytes', function () {
test('compares the bytes sequence as big endian number', function () {
expect(compareBytes([0, 1, 2], [1, 2, 3])).toBe(-1)
})
test('throws when the bytes sequences are of unlike length', function () {
expect(() => compareBytes([0, 1], [1])).toThrow()
})
})
describe('slice', function () {
const val = [1, 2, 3, 4, 5]
test('creates a slice of the same type as first arg', function () {
expect(Array.isArray(slice(val))).toBe(true)
})
test('the 2nd arg is the start position [2:]', function () {
expect(val.slice(2)).toEqual([3, 4, 5])
expect(slice(val, 2)).toEqual([3, 4, 5])
})
test('the 3rd arg is the end position [2:4]', function () {
expect(slice(val, 2, 4)).toEqual([3, 4])
})
test('can slice using negative numbers [-3:]', function () {
expect(slice(val, -3)).toEqual([3, 4, 5])
})
test('can slice using negative numbers [-3:-1]', function () {
expect(slice(val, -3, -1)).toEqual([3, 4])
})
test('the 4th arg is the output class type', function () {
expect(slice(val, 2, 4, Buffer).toJSON().data).toEqual([3, 4])
expect(slice(val, 2, 4, Uint8Array)).toEqual(Uint8Array.from([3, 4]))
})
})
})

View File

@@ -3718,4 +3718,4 @@
"expected_hex": "8D"
}
]
}
}

View File

@@ -1,58 +0,0 @@
const assert = require('assert');
const {Hash160, Hash256, Currency, AccountID} = require('../src/coretypes');
describe('Hash160', function() {
it('has a static width membmer', function() {
assert.equal(Hash160.width, 20);
});
it('inherited by subclasses', function() {
assert.equal(AccountID.width, 20);
assert.equal(Currency.width, 20);
});
it('can be compared against another', function() {
const h1 = Hash160.from('1000000000000000000000000000000000000000');
const h2 = Hash160.from('2000000000000000000000000000000000000000');
const h3 = Hash160.from('0000000000000000000000000000000000000003');
assert(h1.lt(h2));
assert(h3.lt(h2));
});
});
describe('Hash256', function() {
it('has a static width membmer', function() {
assert.equal(Hash256.width, 32);
});
it('has a ZERO_256 member', function() {
assert.equal(
Hash256.ZERO_256.toJSON(),
'0000000000000000000000000000000000000000000000000000000000000000');
});
it('supports getting the nibblet values at given positions', function() {
const h = Hash256.from(
'1359BD0000000000000000000000000000000000000000000000000000000000');
assert.equal(h.nibblet(0), 0x1);
assert.equal(h.nibblet(1), 0x3);
assert.equal(h.nibblet(2), 0x5);
assert.equal(h.nibblet(3), 0x9);
assert.equal(h.nibblet(4), 0x0b);
assert.equal(h.nibblet(5), 0xd);
});
});
describe('Currency', function() {
it('Will have a null iso() for dodgy XRP ', function() {
const bad = Currency.from('0000000000000000000000005852500000000000');
assert.equal(bad.iso(), null);
assert.equal(bad.isNative(), false);
});
it('can be constructed from an Array', function() {
const xrp = Currency.from(new Uint8Array(20));
assert.equal(xrp.iso(), 'XRP');
});
it('throws on invalid reprs', function() {
assert.throws(() => Currency.from(new Uint8Array(19)));
assert.throws(() => Currency.from(1));
assert.throws(() => Currency.from(
'00000000000000000000000000000000000000m'));
});
});

View File

@@ -0,0 +1,56 @@
const { coreTypes } = require('../dist/types')
const { Hash160, Hash256, Currency, AccountID } = coreTypes
describe('Hash160', function () {
test('has a static width membmer', function () {
expect(Hash160.width).toBe(20)
})
test('inherited by subclasses', function () {
expect(AccountID.width).toBe(20)
expect(Currency.width).toBe(20)
})
test('can be compared against another', function () {
const h1 = Hash160.from('1000000000000000000000000000000000000000')
const h2 = Hash160.from('2000000000000000000000000000000000000000')
const h3 = Hash160.from('0000000000000000000000000000000000000003')
expect(h1.lt(h2)).toBe(true)
expect(h3.lt(h2)).toBe(true)
})
})
describe('Hash256', function () {
test('has a static width membmer', function () {
expect(Hash256.width).toBe(32)
})
test('has a ZERO_256 member', function () {
expect(Hash256.ZERO_256.toJSON()).toBe('0000000000000000000000000000000000000000000000000000000000000000')
})
test('supports getting the nibblet values at given positions', function () {
const h = Hash256.from(
'1359BD0000000000000000000000000000000000000000000000000000000000')
expect(h.nibblet(0)).toBe(0x1)
expect(h.nibblet(1)).toBe(0x3)
expect(h.nibblet(2)).toBe(0x5)
expect(h.nibblet(3)).toBe(0x9)
expect(h.nibblet(4)).toBe(0x0b)
expect(h.nibblet(5)).toBe(0xd)
})
})
describe('Currency', function () {
test('Will have a null iso() for dodgy XRP ', function () {
const bad = Currency.from('0000000000000000000000005852500000000000')
expect(bad.iso()).toBeNull()
expect(bad.isNative()).toBe(false)
})
test('can be constructed from an Array', function () {
const xrp = Currency.from(new Uint8Array(20))
expect(xrp.iso()).toBe('XRP')
})
test('throws on invalid reprs', function () {
expect(() => Currency.from(new Uint8Array(19))).toThrow()
expect(() => Currency.from(1)).toThrow()
expect(() => Currency.from(
'00000000000000000000000000000000000000m')).toThrow()
})
})

View File

@@ -1,26 +0,0 @@
const assert = require('assert');
const {loadFixture} = require('./utils');
const ledgerHashes = require('../src/ledger-hashes');
const {transactionTreeHash, ledgerHash, accountStateHash} = ledgerHashes;
describe('Ledger Hashes', function() {
function testFactory(ledgerFixture) {
describe(`can calculate hashes for ${ledgerFixture}`, function() {
const ledger = loadFixture(ledgerFixture);
it('computes correct account state hash', function() {
assert.equal(accountStateHash(ledger.accountState).toHex(),
ledger.account_hash);
});
it('computes correct transaction tree hash', function() {
assert.equal(transactionTreeHash(ledger.transactions).toHex(),
ledger.transaction_hash);
});
it('computes correct ledger header hash', function() {
assert.equal(ledgerHash(ledger).toHex(), ledger.hash);
});
});
}
testFactory('ledger-full-40000.json');
testFactory('ledger-full-38129.json');
});

View File

@@ -0,0 +1,21 @@
const { loadFixture } = require('./utils')
const { transactionTreeHash, ledgerHash, accountStateHash } = require('../dist/ledger-hashes')
describe('Ledger Hashes', function () {
function testFactory (ledgerFixture) {
describe(`can calculate hashes for ${ledgerFixture}`, function () {
const ledger = loadFixture(ledgerFixture)
test('computes correct account state hash', function () {
expect(accountStateHash(ledger.accountState).toHex()).toBe(ledger.account_hash)
})
test('computes correct transaction tree hash', function () {
expect(transactionTreeHash(ledger.transactions).toHex()).toBe(ledger.transaction_hash)
})
test('computes correct ledger header hash', function () {
expect(ledgerHash(ledger).toHex()).toBe(ledger.hash)
})
})
}
testFactory('ledger-full-40000.json')
testFactory('ledger-full-38129.json')
})

View File

@@ -1 +0,0 @@
--reporter spec --slow 500 --require babel-core/register

View File

@@ -1,16 +0,0 @@
const assert = require('assert');
const {quality, binary: {bytesToHex}} = require('../src/coretypes');
describe('Quality encode/decode', function() {
const bookDirectory =
'4627DFFCFF8B5A265EDBD8AE8C14A52325DBFEDAF4F5C32E5D06F4C3362FE1D0';
const expectedQuality = '195796912.5171664';
it('can decode', function() {
const decimal = quality.decode(bookDirectory);
assert.equal(decimal.toString(), expectedQuality);
});
it('can encode', function() {
const bytes = quality.encode(expectedQuality);
assert.equal(bytesToHex(bytes), bookDirectory.slice(-16));
});
});

View File

@@ -0,0 +1,15 @@
const { quality, binary } = require('../dist/coretypes')
describe('Quality encode/decode', function () {
const bookDirectory =
'4627DFFCFF8B5A265EDBD8AE8C14A52325DBFEDAF4F5C32E5D06F4C3362FE1D0'
const expectedQuality = '195796912.5171664'
test('can decode', function () {
const decimal = quality.decode(bookDirectory)
expect(decimal.toString()).toBe(expectedQuality)
})
test('can encode', function () {
const bytes = quality.encode(expectedQuality)
expect(binary.bytesToHex(bytes)).toBe(bookDirectory.slice(-16))
})
})

View File

@@ -1,88 +0,0 @@
const assert = require('assert');
const {ShaMap} = require('../src/shamap.js');
const {binary: {serializeObject}, Hash256, HashPrefix}
= require('../src/coretypes');
const {loadFixture} = require('./utils');
function now() {
return (Number(Date.now())) / 1000;
}
const ZERO =
'0000000000000000000000000000000000000000000000000000000000000000';
function makeItem(indexArg) {
let str = indexArg;
while (str.length < 64) {
str += '0';
}
const index = Hash256.from(str);
const item = {
toBytesSink(sink) {
index.toBytesSink(sink);
},
hashPrefix() {
return [1, 3, 3, 7];
}
};
return [index, item];
}
describe('ShaMap', () => {
now();
it('hashes to zero when empty', () => {
const map = new ShaMap();
assert.equal(map.hash().toHex(), ZERO);
});
it('creates the same hash no matter which order items are added', () => {
let map = new ShaMap();
const items = [
'0',
'1',
'11',
'7000DE445E22CB9BB7E1717589FA858736BAA5FD192310E20000000000000000',
'7000DE445E22CB9BB7E1717589FA858736BAA5FD192310E21000000000000000',
'7000DE445E22CB9BB7E1717589FA858736BAA5FD192310E22000000000000000',
'7000DE445E22CB9BB7E1717589FA858736BAA5FD192310E23000000000000000',
'12',
'122'
];
items.forEach(i => map.addItem(...makeItem(i)));
const h1 = map.hash();
assert(h1.eq(h1));
map = new ShaMap();
items.reverse().forEach(i => map.addItem(...makeItem(i)));
assert(map.hash().eq(h1));
});
function factory(fixture) {
it(`recreate account state hash from ${fixture}`, () => {
const map = new ShaMap();
const ledger = loadFixture(fixture);
// const t = now();
const leafNodePrefix = HashPrefix.accountStateEntry;
ledger.accountState.map((e, i) => {
if (i > 1000 & (i % 1000) === 0) {
console.log(e.index);
console.log(i);
}
const bytes = serializeObject(e);
return {
index: Hash256.from(e.index),
hashPrefix() {
return leafNodePrefix;
},
toBytesSink(sink) {
sink.put(bytes);
}
};
}).forEach(so => map.addItem(so.index, so));
assert.equal(map.hash().toHex(), ledger.account_hash);
// console.log('took seconds: ', (now() - t));
});
}
factory('ledger-full-38129.json');
factory('ledger-full-40000.json');
// factory('ledger-4320277.json');
// factory('14280680.json');
});

View File

@@ -0,0 +1,87 @@
const { ShaMap } = require('../dist/shamap.js')
const { binary, HashPrefix } = require('../dist/coretypes')
const { coreTypes } = require('../dist/types')
const { loadFixture } = require('./utils')
function now () {
return (Number(Date.now())) / 1000
}
const ZERO =
'0000000000000000000000000000000000000000000000000000000000000000'
function makeItem (indexArg) {
let str = indexArg
while (str.length < 64) {
str += '0'
}
const index = coreTypes.Hash256.from(str)
const item = {
toBytesSink (sink) {
index.toBytesSink(sink)
},
hashPrefix () {
return [1, 3, 3, 7]
}
}
return [index, item]
}
describe('ShaMap', () => {
now()
test('hashes to zero when empty', () => {
const map = new ShaMap()
expect(map.hash().toHex()).toBe(ZERO)
})
test('creates the same hash no matter which order items are added', () => {
let map = new ShaMap()
const items = [
'0',
'1',
'11',
'7000DE445E22CB9BB7E1717589FA858736BAA5FD192310E20000000000000000',
'7000DE445E22CB9BB7E1717589FA858736BAA5FD192310E21000000000000000',
'7000DE445E22CB9BB7E1717589FA858736BAA5FD192310E22000000000000000',
'7000DE445E22CB9BB7E1717589FA858736BAA5FD192310E23000000000000000',
'12',
'122'
]
items.forEach(i => map.addItem(...makeItem(i)))
const h1 = map.hash()
expect(h1.eq(h1)).toBe(true)
map = new ShaMap()
items.reverse().forEach(i => map.addItem(...makeItem(i)))
expect(map.hash()).toStrictEqual(h1)
})
function factory (fixture) {
test(`recreate account state hash from ${fixture}`, () => {
const map = new ShaMap()
const ledger = loadFixture(fixture)
// const t = now();
const leafNodePrefix = HashPrefix.accountStateEntry
ledger.accountState.map((e, i) => {
if (i > 1000 & (i % 1000) === 0) {
console.log(e.index)
console.log(i)
}
const bytes = binary.serializeObject(e)
return {
index: coreTypes.Hash256.from(e.index),
hashPrefix () {
return leafNodePrefix
},
toBytesSink (sink) {
sink.put(bytes)
}
}
}).forEach(so => map.addItem(so.index, so))
expect(map.hash().toHex()).toBe(ledger.account_hash)
// console.log('took seconds: ', (now() - t));
})
}
factory('ledger-full-38129.json')
factory('ledger-full-40000.json')
// factory('ledger-4320277.json');
// factory('14280680.json');
})

View File

@@ -1,7 +1,5 @@
const _ = require('lodash');
const assert = require('assert');
const {encodeForSigning, encodeForSigningClaim, encodeForMultisigning} =
require('../src');
const _ = require('lodash')
const { encodeForSigning, encodeForSigningClaim, encodeForMultisigning } = require('../dist')
const tx_json = {
Account: 'r9LqNeG6qHxjeUocjvVki2XR35weJ9mZgQ',
@@ -19,12 +17,12 @@ const tx_json = {
'3CD7B9B',
SigningPubKey:
'ED5F5AC8B98974A3CA843326D9B88CEBD0560177B973EE0B149F782CFAA06DC66A'
};
}
describe('Signing data', function() {
it('can create single signing blobs', function() {
const actual = encodeForSigning(tx_json);
assert.equal(actual,
describe('Signing data', function () {
test('can create single signing blobs', function () {
const actual = encodeForSigning(tx_json)
expect(actual).toBe(
['53545800', // signingPrefix
// TransactionType
'12',
@@ -58,13 +56,13 @@ describe('Signing data', function() {
// VLLength
'14',
'B5F762798A53D543A014CAF8B297CFF8F2F937E8'].join('')
);
});
it('can create multi signing blobs', function() {
const signingAccount = 'rJZdUusLDtY9NEsGea7ijqhVrXv98rYBYN';
const signingJson = _.assign({}, tx_json, {SigningPubKey: ''});
const actual = encodeForMultisigning(signingJson, signingAccount);
assert.equal(actual,
)
})
test('can create multi signing blobs', function () {
const signingAccount = 'rJZdUusLDtY9NEsGea7ijqhVrXv98rYBYN'
const signingJson = _.assign({}, tx_json, { SigningPubKey: '' })
const actual = encodeForMultisigning(signingJson, signingAccount)
expect(actual).toBe(
['534D5400', // signingPrefix
// TransactionType
'12',
@@ -100,15 +98,15 @@ describe('Signing data', function() {
'B5F762798A53D543A014CAF8B297CFF8F2F937E8',
// signingAccount suffix
'C0A5ABEF242802EFED4B041E8F2D4A8CC86AE3D1'].join('')
);
});
it('can create claim blob', function() {
)
})
test('can create claim blob', function () {
const channel =
'43904CBFCDCEC530B4037871F86EE90BF799DF8D2E0EA564BC8A3F332E4F5FB1'
const amount = '1000'
const json = {channel, amount}
const json = { channel, amount }
const actual = encodeForSigningClaim(json)
assert.equal(actual, [
expect(actual).toBe([
// hash prefix
'434C4D00',
// channel ID
@@ -117,4 +115,4 @@ describe('Signing data', function() {
'00000000000003E8'
].join(''))
})
});
})

View File

@@ -1,8 +1,7 @@
const assert = require('assert');
const {
encode,
decode
} = require('../src')
} = require('../dist')
// Notice: no Amount or Fee
const tx_json = {
@@ -20,7 +19,7 @@ const tx_json = {
// TxnSignature,
// Signature,
// SigningPubKey
};
}
const amount_parameters_message = input => {
// disables the ESLint rule on the whole rest of the file
@@ -41,84 +40,82 @@ Thus the largest serializable IOU value is:
And the smallest:
0.000000000000000000000000000000000000000000000000000000000000000000000000000000001
`;
};
`
}
describe('encoding and decoding tx_json', function() {
it('can encode tx_json without Amount or Fee', function() {
const encoded = encode(tx_json);
const decoded = decode(encoded);
assert.deepStrictEqual(tx_json, decoded);
});
it('can encode tx_json with Amount and Fee', function() {
describe('encoding and decoding tx_json', function () {
test('can encode tx_json without Amount or Fee', function () {
const encoded = encode(tx_json)
const decoded = decode(encoded)
expect(tx_json).toEqual(decoded)
})
test('can encode tx_json with Amount and Fee', function () {
const my_tx = Object.assign({}, tx_json, {
Amount: '1000',
Fee: '10'
});
const encoded = encode(my_tx);
const decoded = decode(encoded);
assert.deepStrictEqual(my_tx, decoded);
});
it('throws when Amount is invalid', function() {
})
const encoded = encode(my_tx)
const decoded = decode(encoded)
expect(my_tx).toEqual(decoded)
})
test('throws when Amount is invalid', function () {
const my_tx = Object.assign({}, tx_json, {
Amount: '1000.001',
Fee: '10'
});
assert.throws(() => {
encode(my_tx);
}, {
})
expect(() => {
encode(my_tx)
}).toThrow({
name: 'Error',
message: amount_parameters_message('1000.001')
});
});
it('throws when Fee is invalid', function() {
})
})
test('throws when Fee is invalid', function () {
const my_tx = Object.assign({}, tx_json, {
Amount: '1000',
Fee: '10.123'
});
assert.throws(() => {
encode(my_tx);
}, {
})
expect(() => {
encode(my_tx)
}).toThrow({
name: 'Error',
message: amount_parameters_message('10.123')
});
});
it('throws when Amount and Fee are invalid', function() {
})
})
test('throws when Amount and Fee are invalid', function () {
const my_tx = Object.assign({}, tx_json, {
Amount: '1000.789',
Fee: '10.123'
});
assert.throws(() => {
encode(my_tx);
}, {
})
expect(() => {
encode(my_tx)
}).toThrow({
name: 'Error',
message: amount_parameters_message('1000.789')
});
});
it('throws when Amount is a number instead of a string-encoded integer',
function() {
})
})
test('throws when Amount is a number instead of a string-encoded integer',
function () {
const my_tx = Object.assign({}, tx_json, {
Amount: 1000.789
});
assert.throws(() => {
encode(my_tx);
},
{
})
expect(() => {
encode(my_tx)
}).toThrow({
name: 'Error',
message: 'unsupported value: 1000.789'
});
});
it('throws when Fee is a number instead of a string-encoded integer',
function() {
})
})
test('throws when Fee is a number instead of a string-encoded integer',
function () {
const my_tx = Object.assign({}, tx_json, {
Amount: 1234.56
});
assert.throws(() => {
encode(my_tx);
},
{
})
expect(() => {
encode(my_tx)
}).toThrow({
name: 'Error',
message: 'unsupported value: 1234.56'
});
});
});
})
})
})

View File

@@ -1,38 +0,0 @@
const _ = require('lodash');
const assert = require('assert');
const coreTypes = require('../src/types');
const {SerializedType} = require('../src/types/serialized-type');
describe('SerializedType interfaces', () => {
_.forOwn(coreTypes, (Value, name) => {
it(`${name} has a \`from\` static constructor`, () => {
assert(Value.from && Value.from !== Array.from);
});
it(`${name} has a default constructor`, () => {
/* eslint-disable no-new*/
new Value();
/* eslint-enable no-new*/
});
it(`${name}.from will return the same object`, () => {
const instance = new Value();
assert(Value.from(instance) === instance);
});
it(`${name} instances have toBytesSink`, () => {
assert(new Value().toBytesSink);
});
it(`${name} instances have toJSON`, () => {
assert(new Value().toJSON);
});
it(`${name}.from(json).toJSON() == json`, () => {
const newJSON = new Value().toJSON();
assert.deepEqual(Value.from(newJSON).toJSON(), newJSON);
});
describe(`${name} supports all methods of the SerializedType mixin`, () => {
_.keys(SerializedType).forEach(k => {
it(`new ${name}.prototype.${k} !== undefined`, () => {
assert.notEqual(Value.prototype[k], undefined);
});
});
});
});
});

View File

@@ -0,0 +1,37 @@
const _ = require('lodash')
const { coreTypes } = require('../dist/types')
const { SerializedType } = require('../dist/types/serialized-type')
describe('SerializedType interfaces', () => {
_.forOwn(coreTypes, (Value, name) => {
test(`${name} has a \`from\` static constructor`, () => {
expect(Value.from && Value.from !== Array.from).toBe(true)
})
test(`${name} has a default constructor`, () => {
/* eslint-disable no-new */
new Value()
/* eslint-enable no-new */
})
test(`${name}.from will return the same object`, () => {
const instance = new Value()
expect(Value.from(instance) === instance).toBe(true)
})
test(`${name} instances have toBytesSink`, () => {
expect(new Value().toBytesSink).not.toBe(undefined)
})
test(`${name} instances have toJSON`, () => {
expect(new Value().toJSON).not.toBe(undefined)
})
test(`${name}.from(json).toJSON() == json`, () => {
const newJSON = new Value().toJSON()
expect(Value.from(newJSON).toJSON()).toEqual(newJSON)
})
describe(`${name} supports all methods of the SerializedType mixin`, () => {
_.keys(SerializedType).forEach(k => {
test(`new ${name}.prototype.${k} !== undefined`, () => {
expect(Value.prototype[k]).not.toBe(undefined)
})
})
})
})
})

View File

@@ -1,38 +0,0 @@
const assert = require('assert');
const coreTypes = require('../src/coretypes');
/* eslint-disable no-unused-vars */
const {UInt8, UInt16, UInt32, UInt64} = coreTypes;
/* eslint-enable no-unused-vars */
function compareToTests() {
function check(expr, is) {
it(expr, function() {
/* eslint-disable no-eval */
assert.equal(eval(expr), is);
/* eslint-enable no-eval */
});
}
check('UInt8.from(124).compareTo(UInt64.from(124))', 0);
check('UInt64.from(124).compareTo(UInt8.from(124))', 0);
check('UInt64.from(124).compareTo(UInt8.from(123))', 1);
check('UInt8.from(124).compareTo(UInt8.from(13))', 1);
check('UInt8.from(124).compareTo(124)', 0);
check('UInt64.from(124).compareTo(124)', 0);
check('UInt64.from(124).compareTo(123)', 1);
check('UInt8.from(124).compareTo(13)', 1);
}
function valueOfTests() {
it('The Uint classes work with |= operator', function() {
let val = UInt8.from(1);
val |= 0x2;
assert.equal(val, 3);
});
}
describe('Uint*', function() {
describe('compareToTests', compareToTests);
describe('valueOfTests', valueOfTests);
});

View File

@@ -0,0 +1,40 @@
const { coreTypes } = require('../dist/types')
const { UInt8, UInt64 } = coreTypes
test('compareToTests', () => {
expect(UInt8.from(124).compareTo(UInt64.from(124))).toBe(-0)
})
test('compareToTest', () => {
expect(UInt64.from(124).compareTo(UInt8.from(124))).toBe(0)
})
test('compareToTest', () => {
expect(UInt64.from(124).compareTo(UInt8.from(123))).toBe(1)
})
test('compareToTest', () => {
expect(UInt8.from(124).compareTo(UInt8.from(13))).toBe(1)
})
test('compareToTest', () => {
expect(UInt8.from(124).compareTo(124)).toBe(0)
})
test('compareToTest', () => {
expect(UInt64.from(124).compareTo(124)).toBe(0)
})
test('compareToTest', () => {
expect(UInt64.from(124).compareTo(123)).toBe(1)
})
test('compareToTest', () => {
expect(UInt8.from(124).compareTo(13)).toBe(1)
})
test('valueOfTests', () => {
let val = UInt8.from(1)
val |= 0x2
expect(val).toBe(3)
})

View File

@@ -1,83 +1,24 @@
const intercept = require('intercept-stdout');
const fs = require('fs');
const fsExtra = require('fs-extra');
const assert = require('assert');
const Decimal = require('decimal.js');
const {parseBytes} = require('../src/utils/bytes-utils');
const fs = require('fs')
const { parseBytes } = require('../dist/utils/bytes-utils')
function hexOnly(hex) {
return hex.replace(/[^a-fA-F0-9]/g, '');
function hexOnly (hex) {
return hex.replace(/[^a-fA-F0-9]/g, '')
}
function unused() {}
function unused () {}
function captureLogsAsync() {
let log = '';
const unhook = intercept(txt => {
log += txt;
return '';
});
return function() {
unhook();
return log;
};
function parseHexOnly (hex, to) {
return parseBytes(hexOnly(hex), to)
}
function captureLogs(func) {
const finished = captureLogsAsync();
try {
func();
} catch (e) {
const log = finished();
console.error(log);
throw e;
}
return finished();
function loadFixture (relativePath) {
const fn = __dirname + '/fixtures/' + relativePath
return require(fn)
}
function parseHexOnly(hex, to) {
return parseBytes(hexOnly(hex), to);
}
function loadFixture(relativePath) {
const fn = __dirname + '/fixtures/' + relativePath;
return require(fn);
}
function isBufferOrString(val) {
return Buffer.isBuffer(val) || (typeof val === 'string');
}
function loadFixtureText(relativePath) {
const fn = __dirname + '/fixtures/' + relativePath;
return fs.readFileSync(fn).toString('utf8');
}
function fixturePath(relativePath) {
return __dirname + '/fixtures/' + relativePath;
}
function prettyJSON(val) {
return JSON.stringify(val, null, 2);
}
function writeFixture(relativePath, data) {
const out = isBufferOrString(data) ? data : prettyJSON(data);
return fsExtra.outputFileSync(fixturePath(relativePath), out);
}
function assertEqualAmountJSON(actual, expected) {
const typeA = (typeof actual);
assert(typeA === (typeof expected));
if (typeA === 'string') {
assert.equal(actual, expected);
return;
}
assert.equal(actual.currency, expected.currency);
assert.equal(actual.issuer, expected.issuer);
assert(actual.value === expected.value ||
new Decimal(actual.value).equals(
new Decimal(expected.value)));
function loadFixtureText (relativePath) {
const fn = __dirname + '/fixtures/' + relativePath
return fs.readFileSync(fn).toString('utf8')
}
module.exports = {
@@ -85,9 +26,5 @@ module.exports = {
parseHexOnly,
loadFixture,
loadFixtureText,
assertEqualAmountJSON,
writeFixture,
unused,
captureLogs,
captureLogsAsync
};
unused
}