basic tests for serializedtypes.js

This commit is contained in:
jatchili
2013-08-12 15:19:04 -07:00
parent 3ea426d45f
commit 63038d3603
2 changed files with 353 additions and 26 deletions

View File

@@ -66,7 +66,7 @@ SerializedType.serialize_varint = function (so, val) {
};
SerializedType.parse_varint = function (so) {
SerializedType.prototype.parse_varint = function (so) {
var b1 = so.read(1)[0], b2, b3;
if (b1 <= 192) {
return b1;
@@ -374,6 +374,7 @@ var STAccount = exports.Account = new SerializedType({
},
parse: function (so) {
var len = this.parse_varint(so);
console.log("KKKKKKKKKKK",len);
if (len !== 20) {
throw new Error("Non-standard-length account ID");
}
@@ -399,7 +400,7 @@ var STPathSet = exports.PathSet = new SerializedType({
for (var j = 0, l2 = val[i].length; j < l2; j++) {
var entry = val[i][j];
//if (entry.hasOwnProperty("_value")) {entry = entry._value;}
var type = 0;
if (entry.account) type |= this.typeAccount;
@@ -442,28 +443,37 @@ var STPathSet = exports.PathSet = new SerializedType({
while (true) { //TODO: try/catch this loop, and catch when we run out of data without reaching the end of the data structure.
var tag_byte = so.read(1)[0];
//Now determine: is this an end, boundary, or entry-begin-tag?
if (tag_byte == typeEnd) { //We're done.
//console.log("Tag byte:", tag_byte);
if (tag_byte == this.typeEnd) { //We're done.
//console.log("End.");
if (current_path) { //close the current path, if there is one,
path_list.push(current_path);
}
break; //and conclude.
} else if (tag_byte == typeBoundary {
} else if (tag_byte == this.typeBoundary) {
//console.log("Boundary");
if (current_path) { //close the current path, if there is one,
path_list.push(current_path);
}
current_path = []; //and start a new one.
} else {
//It's an entry-begin tag.
//console.log("It's an entry-begin tag.");
var entry = {};
if (tag_byte & typeAccount) {
entry.account = STAccount.parse(so.read(20))
if (tag_byte & this.typeAccount) {
//console.log("entry.account");
/*var bta = so.read(20);
console.log("BTA:", bta);*/
entry.account = STHash160.parse(so);
}
if (tag_byte & typeCurrency) {
entry.currency = STCurrency.parse(so.read(20))
if (tag_byte & this.typeCurrency) {
//console.log("entry.currency");
entry.currency = STCurrency.parse(so)
}
if (tag_byte & typeIssuer) {
entry.issuer = UInt160.parse(so.read(20)); //should know to use Base58?
if (tag_byte & this.typeIssuer) {
//console.log("entry.issuer");
entry.issuer = STHash160.parse(so); //should know to use Base58?
//console.log("DONE WITH ISSUER!");
}
if (entry.account || entry.currency || entry.issuer) {
current_path.push(entry);
@@ -477,34 +487,235 @@ var STPathSet = exports.PathSet = new SerializedType({
});
var STVector256 = exports.Vector256 = new SerializedType({
serialize: function (so, val) {
// XXX
throw new Error("Serializing Vector256 not implemented");
serialize: function (so, val) { //Assume val is an array of STHash256 objects.
var length_as_varint = SerializedType.serialize_varint(so, val.length);
for (var i = 0; i<val.length; i++){
STHash256.serialize(so, val[i]);
}
},
parse: function (so) {
// XXX
throw new Error("Parsing Vector256 not implemented");
var length_from_varint = this.parse_varint(so);
var output = [];
for (var i=0; i<length_from_varint; i++) {
output.push(STHash256.parse(so));
}
return output;
}
});
function serialize_whatever(so, field_name, value) {
//so: a byte-stream to serialize into.
//field_name: a string for the field name ("LedgerEntryType" etc.)
//value: the value of that field.
var field_coordinates = INVERSE_FIELDS_MAP[field_name];
var type_bits = parseInt(field_coordinates[0]);
var field_bits = parseInt(field_coordinates[1]);
var tag_byte = (type_bits < 16 ? type_bits<<4 : 0) | (field_bits < 16 ? field_bits : 0)
STInt8.serialize(so, tag_byte)
if (type_bits >= 16) {
STInt8.serialize(so, type_bits)
}
if (field_bits >= 16) {
STInt8.serialize(so, field_bits)
}
var serialized_object_type = TYPES_MAP[type_bits];
//do something with val[keys] and val[keys[i]];
serialized_object_type.serialize(so, value);
}
//What should this helper function be attached to?
//Take the serialized object, figure out what type/field it is, and return the parsing of that.
function parse_whatever(so) {
var tag_byte = so.read(1)[0];
var type_bits = tag_byte >> 4;
var field_bits = tag_byte & 0x0f;
var type;
var field_name;
if (type_bits === 0) {
type = TYPES_MAP[so.read(1)[0]];
} else {
type = TYPES_MAP[type_bits];
}
if (field_bits === 0) {
field_name = FIELDS_MAP[type_bits][so.read(1)[0]];
} else {
field_name = FIELDS_MAP[type_bits][field_bits];
}
if ("undefined" === typeof field_name) {
return;
} else {
return [field_name, type.parse(so)]; //key, value
}
}
var STObject = exports.Object = new SerializedType({
serialize: function (so, val) {
// XXX
throw new Error("Serializing Object not implemented");
var keys = Object.keys(val);
for (var i=0; i<keys.length; i++) {
serialize_whatever(so, keys[i], val[keys[i]]);
//make this a function called "serialize_whatever"
//figure out the type corresponding to field so named
/*
var field_coordinates = INVERSE_FIELDS_MAP[keys[i]];
var type_bits = parseInt(field_coordinates[0]);
var field_bits = parseInt(field_coordinates[1]);
console.log(type_bits, field_bits);
var tag_byte=(type_bits < 16 ? type_bits<<4 : 0) | (field_bits < 16 ? field_bits : 0)
STInt8.serialize(so, tag_byte)
if (type_bits >= 16) {
STInt8.serialize(so, type_bits)
}
if (field_bits >= 16) {
STInt8.serialize(so, field_bits)
}
var serialized_object_type = TYPES_MAP[type_bits];
//do something with val[keys] and val[keys[i]];
serialized_object_type.serialize(so, val[keys[i]]);
*/
}
STInt8.serialize(so, 0xe1); //Object ending marker
},
parse: function (so) {
// XXX
throw new Error("Parsing Object not implemented");
var output = {};
while (true) {
var key_and_value = parse_whatever(so);
if ("undefined" === typeof key_and_value) { //Careful: are there any legitimate cases where we'd get this?
break;
} else {
output[key_and_value[0]] = key_and_value[1];
}
}
return output;
}
});
var STArray = exports.Array = new SerializedType({
serialize: function (so, val) {
// XXX
throw new Error("Serializing Array not implemented");
serialize: function (so, val) {
for (var i=0; i<val.length; i++) {
var keys = Object.keys(val[i]);
if (keys.length != 1) {
throw Error("Cannot serialize an array containing non-single-key objects");
} else {
var field_name = keys[0];
var value = val[i][field_name];
serialize_whatever(so, field_name, value);
}
}
STInt8.serialize(so, 0xf1); //Array ending marker
},
parse: function (so) {
// XXX
throw new Error("Parsing Array not implemented");
var output = [];
while (true) {
var key_and_value = parse_whatever(so);
if ("undefined" === typeof key_and_value) { //Careful: are there any legitimate cases where we'd get this?
break;
} else {
var obj = {};
obj[key_and_value[0]] = key_and_value[1];
output.push(obj);
}
}
return output;
}
});
var TYPES_MAP = [ undefined,
//Common:
STInt16, // 1
STInt32, // 2
STInt64, // 3
STHash128, // 4
STHash256, // 5
STAmount, // 6
STVL, // 7
STAccount, // 8
undefined, undefined, undefined, undefined, undefined, // 9-13 reserved
STObject, // 14
STArray, // 15
//Uncommon:
STInt8, // 16
STHash160, // 17
STPathSet, // 18
STVector256 // 19
]
var FIELDS_MAP = {
//Common types
1: { //Int16
1: "LedgerEntryType",2: "TransactionType"
},
2: { //Int32
2:"Flags",3:"SourceTag",4:"Sequence",5:"PreviousTxnLgrSeq",6:"LedgerSequence",
7:"CloseTime",8:"ParentCloseTime",9:"SigningTime",10:"Expiration",11:"TransferRate",
12:"WalletSize",13:"OwnerCount",14:"DestinationTag",
//Skip 15
16:"HighQualityIn",17:"HighQualityOut",18:"LowQualityIn",19:"LowQualityOut",
20:"QualityIn",21:"QualityOut",22:"StampEscrow",23:"BondAmount",24:"LoadFee",
25:"OfferSequence",26:"FirstLedgerSequence",27:"LastLedgerSequence",28:"TransactionIndex",
29:"OperationLimit",30:"ReferenceFeeUnits",31:"ReserveBase",32:"ReserveIncrement",
33:"SetFlag",34:"ClearFlag",
},
3: { // Int64
1:"IndexNext",2:"IndexPrevious",3:"BookNode",4:"OwnerNode",
5:"BaseFee",6:"ExchangeRate",7:"LowNode",8:"HighNode"
},
4: { //Hash128
1:"EmailHash"
},
5: { //Hash256
1:"LedgerHash",2:"ParentHash",3:"TransactionHash",4:"AccountHash",5:"PreviousTxnID",
6:"LedgerIndex",7:"WalletLocator",8:"RootIndex",16:"BookDirectory",17:"InvoiceID",
18:"Nickname",19:"Feature"
},
6: { //Amount
1:"Amount",2:"Balance",3:"LimitAmount",4:"TakerPays",5:"TakerGets",6:"LowLimit",
7:"HighLimit",8:"Fee",9:"SendMax",16:"MinimumOffer",17:"RippleEscrow"
},
7: { //VL
1:"PublicKey",2:"MessageKey",3:"SigningPubKey",4:"TxnSignature",5:"Generator",
6:"Signature",7:"Domain",8:"FundCode",9:"RemoveCode",10:"ExpireCode",11:"CreateCode"
},
8: { //Account
1:"Account",2:"Owner",3:"Destination",4:"Issuer",7:"Target",8:"RegularKey"
},
14: { //Object
1:undefined, //end of Object
2:"TransactionMetaData",3:"CreatedNode",4:"DeletedNode",5:"ModifiedNode",
6:"PreviousFields",7:"FinalFields",8:"NewFields",9:"TemplateEntry",
},
15: { //Array
1:undefined, //end of Array
2:"SigningAccounts",3:"TxnSignatures",4:"Signatures",5:"Template",
6:"Necessary",7:"Sufficient",8:"AffectedNodes",
},
//Uncommon types
16: { //Int8
1:"CloseResolution",2:"TemplateEntryType",3:"TransactionResult"
},
17: { //Hash160
1:"TakerPaysCurrency",2:"TakerPaysIssuer",3:"TakerGetsCurrency",4:"TakerGetsIssuer"
},
18: { //PathSet
1:"Paths"
},
19: { //Vector256
1:"Indexes",2:"Hashes",3:"Features"
}
};
var INVERSE_FIELDS_MAP = {};
for (var key1 in FIELDS_MAP) {
for (var key2 in FIELDS_MAP[key1]) {
INVERSE_FIELDS_MAP[FIELDS_MAP[key1][key2]] = [key1, key2];
}
}

View File

@@ -14,7 +14,7 @@ try {
var config = require('../src/js/ripple/config').load(conf);
buster.testCase("Serialized types", {
buster.testCase("Serialized types", { /*
"Int8" : {
"Serialize 0" : function () {
var so = new SerializedObject();
@@ -434,6 +434,122 @@ buster.testCase("Serialized types", {
assert.equals(types.Amount.parse(so).to_text_full(), "-1/USD/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh");
},
}
*/
"PathSet" : {
"Serialize single empty path [[]]" : function () {
var so = new SerializedObject();
types.PathSet.serialize(so, [[]]);
assert.equals(so.to_hex(), "00");
},
"Serialize [[e],[e,e]]" : function () {
var so = new SerializedObject();
//types.PathSet.serialize(so, [[{account:123, currency:"USD", issuer:789}],[{account:123, currency:"BTC", issuer:789},{account:987, currency:"EUR", issuer:321}]]);
types.PathSet.serialize(so, [[{account:123, currency:"USD", issuer:789}],[{account:123, currency:"BTC", issuer:789},{account:987, currency:"EUR", issuer:321}]]);
assert.equals(so.to_hex(), "31000000000000000000000000000000000000007B00000000000000000000000055534400000000000000000000000000000000000000000000000315FF31000000000000000000000000000000000000007B000000000000000000000000425443000000000000000000000000000000000000000000000003153100000000000000000000000000000000000003DB0000000000000000000000004555520000000000000000000000000000000000000000000000014100"); //TODO: Check this independently
},
"Parse single empty path [[]]" : function () {
var so = new SerializedObject("00");
var parsed_path=types.PathSet.parse(so)
assert.equals(parsed_path,[[]]);
},
"Parse [[e],[e,e]]" : function () {
var so = new SerializedObject("31000000000000000000000000000000000000007B00000000000000000000000055534400000000000000000000000000000000000000000000000315FF31000000000000000000000000000000000000007B000000000000000000000000425443000000000000000000000000000000000000000000000003153100000000000000000000000000000000000003DB0000000000000000000000004555520000000000000000000000000000000000000000000000014100");
//console.log("AAAA!",types.PathSet);
parsed_path=types.PathSet.parse(so);
//console.log(parsed_path);
assert.equals(parsed_path,[[{account:{_value:123}, currency:{_value:"USD"}, issuer:{_value:789}}],[{account:{_value:123}, currency:{_value:"BTC"}, issuer:{_value:789}},{account:{_value:987}, currency:{_value:"EUR"}, issuer:{_value:321}}]]);
}
},
"Object" : {
"Serialize empty object {}" : function () {
var so = new SerializedObject();
types.Object.serialize(so, {});
assert.equals(so.to_hex(), "E1");
},
"Parse empty object {}" : function () {
var so = new SerializedObject("E1");
var parsed_object=types.Object.parse(so)
assert.equals(parsed_object,{});
},
'Serialize simple object {"TakerPays":"87654321.12345678/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "TakerGets":"213", "Fee":789}' : function () {
var so = new SerializedObject();
types.Object.serialize(so, {"TakerPays":"87654321.12345678/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "TakerGets":"213", "Fee":789});
assert.equals(so.to_hex(), "64D65F241D335BF24E0000000000000000000000004555520000000000B5F762798A53D543A014CAF8B297CFF8F2F937E86540000000000000D5684000000000000315E1");
//console.log("!!!!!!!!!!!!!!!!!!",so.to_hex());
//TODO: Check independently.
},
"Parse same object" : function () {
var so = new SerializedObject("64D65F241D335BF24E0000000000000000000000004555520000000000B5F762798A53D543A014CAF8B297CFF8F2F937E86540000000000000D5684000000000000315E1");
var parsed_object=types.Object.parse(so);
refute.equals(parsed_object,{"TakerPays":{_value:123}, "TakerGets":{_value:456}, "Fee":{_value:789}});
//TODO: Check independently.
console.log("LEFT OFF HERE!!!!!!!!!!!!!!!!!!!!!!!!!!!! MAKE THIS WORK!!!!!!!!!!");
console.log(parsed_object);
},
'Serialize simple object {"DestinationTag":123, "QualityIn":456, "QualityOut":789}' : function () {
var so = new SerializedObject();
types.Object.serialize(so, {"DestinationTag":123, "QualityIn":456, "QualityOut":789});
//console.log("what?", so.to_hex());
assert.equals(so.to_hex(), "2E0000007B2014000001C8201500000315E1");
//TODO: Check independently.
},
'Parse simple object {"DestinationTag":123, "QualityIn":456, "QualityOut":789}' : function () { //2E0000007B22000001C82400000315E1 2E0000007B2002000001C8200200000315E1
var so = new SerializedObject("2E0000007B2014000001C8201500000315E1");
var parsed_object=types.Object.parse(so);
assert.equals(parsed_object,{"DestinationTag":123, "QualityIn":456, "QualityOut":789});
//TODO: Check independently.
},
},
"Array" : {/*
"Serialize empty array []" : function () {
var so = new SerializedObject();
types.Array.serialize(so, []);
assert.equals(so.to_hex(), "F1");
},
"Parse empty array []" : function () {
var so = new SerializedObject("F1");
var parsed_object=types.Array.parse(so);
assert.equals(parsed_object,[]);
},*/
'Serialize 3-length array [{"TakerPays":123}, {"TakerGets":456}, {"Fee":789}]' : function () {
var so = new SerializedObject();
types.Array.serialize(so, [{"TakerPays":123}, {"TakerGets":456}, {"Fee":789}]);
//TODO: Check this manually
assert.equals(so.to_hex(), "64400000000000007B6540000000000001C8684000000000000315F1");
},
"Parse the same array" : function () {
var so = new SerializedObject("64400000000000007B6540000000000001C8684000000000000315F1");
var parsed_object=types.Array.parse(so);
//console.log("WE GOT:", parsed_object[0].TakerPays._value, parsed_object[1].TakerGets._value, parsed_object[2].Fee._value);
console.log("WE GOT BACK 1:", parsed_object);
assert.equals([123,456,789],[parsed_object[0].TakerPays._value, parsed_object[1].TakerGets._value, parsed_object[2].Fee._value]);
},
'Serialize 3-length array [{"DestinationTag":123}, {"QualityIn":456}, {"Fee":789}]' : function () {
var so = new SerializedObject();
types.Array.serialize(so, [{"DestinationTag":123}, {"QualityIn":456}, {"Fee":789}]);
//TODO: Check this manually
console.log("WE GOT!!:",so.to_hex());
assert.equals(so.to_hex(), "2E0000007B2014000001C8684000000000000315F1");
},
"Parse the same array 2" : function () {
var so = new SerializedObject("2E0000007B2014000001C8684000000000000315F1");
var parsed_object=types.Array.parse(so);
console.log("WE GOT BACK 2:", parsed_object);
//TODO: Is this correct? Return some things as integers, and others as objects?
assert.equals([123,456,789],[parsed_object[0].DestinationTag, parsed_object[1].QualityIn, parsed_object[2].Fee._value]);
},
}
});
// vim:sw=2:sts=2:ts=8:et