From 0ec3f3001c717a19ff617a8cf82934048f8558b9 Mon Sep 17 00:00:00 2001 From: Jeff Smale <6363749+jeffsmale90@users.noreply.github.com> Date: Mon, 28 Mar 2022 18:34:53 +1300 Subject: [PATCH 1/9] fix: Add tests for json-rpc-data and address to describe expected behaviour #1594 --- .../ethereum/address/tests/index.test.ts | 16 ++- .../utils/tests/json-rpc-data.test.ts | 97 +++++++++++++++++++ 2 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 src/packages/utils/tests/json-rpc-data.test.ts diff --git a/src/chains/ethereum/address/tests/index.test.ts b/src/chains/ethereum/address/tests/index.test.ts index d2b19a28e3..ee259893a4 100644 --- a/src/chains/ethereum/address/tests/index.test.ts +++ b/src/chains/ethereum/address/tests/index.test.ts @@ -1,6 +1,18 @@ import assert from "assert"; -import ethereumAddress from "../"; +import {Address} from "../"; describe("@ganache/ethereum-address", () => { - it("needs tests"); + it("should pad an address to 20 bytes", () => { + const address = new Address("0x1"); + const stringifiedAddress = address.toString(); + + assert.equal(stringifiedAddress, "0x0000000000000000000000000000000000000001"); + }); + + it("should pad an address to the specified length", () => { + const address = new Address("0x1"); + const stringifiedAddress = address.toString(1); + + assert.equal(stringifiedAddress, "0x01"); + }); }); diff --git a/src/packages/utils/tests/json-rpc-data.test.ts b/src/packages/utils/tests/json-rpc-data.test.ts new file mode 100644 index 0000000000..d5f43a230b --- /dev/null +++ b/src/packages/utils/tests/json-rpc-data.test.ts @@ -0,0 +1,97 @@ +import assert from "assert"; +import {Data} from ".."; + +describe("json-rpc-data", () => { + describe("Data", () => { + it("should stringify without specifying byteLength", () => { + const cases = [ + {input: "0x1", expected: "0x1"}, // I'm not sure whether this is the correct behaviour - should it return a single byte length string - ie 0x01? + {input: "0x01", expected: "0x01"}, + {input: "0x0123456789abcdef", expected: "0x0123456789abcdef"}, + {input: Buffer.from([0x01]), expected: "0x01"} + ]; + + cases.forEach(c => { + const d = new Data(c.input); + const stringified = d.toString(); + + assert.equal(stringified, c.expected); + }); + }); + + it("should stringify to fixed byteLength", () => { + const cases = [ + {input: "0x1", length: 1, expected: "0x01"}, + {input: "0x01", length: 2, expected: "0x0001"}, + {input: "0x01", length: 10, expected: "0x00000000000000000001"}, + {input: Buffer.from([0x01]), length: 2, expected: "0x0001"} + ]; + + cases.forEach(c => { + const d = new Data(c.input); + const stringified = d.toString(c.length); + + assert.equal(stringified, c.expected); + }); + }); + + it("should stringify and truncate to a shorter byteLength", () => { + const cases = [ + {input: "0x0123", length: 1, expected: "0x01"}, + {input: "0x0123456789abcdef", length: 2, expected: "0x0123"}, + {input: Buffer.from([0x01, 0x23]), length: 1, expected: "0x01"} + ]; + + cases.forEach(c => { + const d = new Data(c.input); + const stringified = d.toString(c.length); + + assert.equal(stringified, c.expected); + }); + }); + + it("should stringify to the byteLength specified in the constructor", () => { + const cases = [ + {input: "0x01", constructorLength: 1, expected: "0x01"}, + {input: "0x01", constructorLength: 10, expected: "0x00000000000000000001"}, + {input: "0x0123456789abcdef", constructorLength: 2, expected: "0x0123"}, + {input: Buffer.from([0x01, 0x23]), constructorLength: 1, expected: "0x01"}, + {input: Buffer.from([0x01]), constructorLength: 2, expected: "0x0001"} + ]; + + cases.forEach(c => { + const d = new Data(c.input, c.constructorLength); + const stringified = d.toString(); + + assert.equal(stringified, c.expected); + }); + }); + + it("should stringify to the byteLength specified in toString, over the byteLength specified in the constructor", () => { + const cases = [ + {input: "0x01", constructorLength: 2, length: 1, expected: "0x01"}, + {input: "0x01", constructorLength: 1, length: 10, expected: "0x00000000000000000001"}, + {input: "0x0123456789abcdef", constructorLength: 1, length: 2, expected: "0x0123"}, + {input: Buffer.from([0x01, 0x23]), constructorLength: 2, length: 1, expected: "0x01"}, + {input: Buffer.from([0x01]), constructorLength: 1, length: 2, expected: "0x0001"} + ]; + + cases.forEach(c => { + const d = new Data(c.input, c.constructorLength); + const stringified = d.toString(c.length); + + assert.equal(stringified, c.expected); + }); + }); + + it("should fail with invalid byte lengths", () => { + const invalidByteLengths = [ -1, 0, "1", {}, [], null, NaN ]; // undefined is a valid value + + const d = new Data("0x01"); + + invalidByteLengths.forEach(byteLength => { + assert.throws(() => d.toString(byteLength), { message: "byteLength must be a number greater than 0" }, `Invalid bytelength provided: <${typeof byteLength}>: ${byteLength}`); + }); + }); + }); +}); From cd833af862963824ac140398f8718f038e9bf086 Mon Sep 17 00:00:00 2001 From: Jeff Smale <6363749+jeffsmale90@users.noreply.github.com> Date: Tue, 29 Mar 2022 12:22:00 +1300 Subject: [PATCH 2/9] fix: fix toString() methods for json-rpc-data, add rough tests for json-rpc-data and address types --- .../ethereum/address/tests/index.test.ts | 7 +++++ .../things/json-rpc/json-rpc-base-types.ts | 1 + .../src/things/json-rpc/json-rpc-data.ts | 31 +++++++++---------- .../utils/tests/json-rpc-data.test.ts | 20 +++++++++--- 4 files changed, 38 insertions(+), 21 deletions(-) diff --git a/src/chains/ethereum/address/tests/index.test.ts b/src/chains/ethereum/address/tests/index.test.ts index ee259893a4..5c9a88d31f 100644 --- a/src/chains/ethereum/address/tests/index.test.ts +++ b/src/chains/ethereum/address/tests/index.test.ts @@ -15,4 +15,11 @@ describe("@ganache/ethereum-address", () => { assert.equal(stringifiedAddress, "0x01"); }); + + it("should create an address from a 20 byte address string", () => { + const address = new Address("0x2104859394604359378433865360947116707876"); + const stringifiedAddress = address.toString(); + + assert.equal(stringifiedAddress, "0x2104859394604359378433865360947116707876"); + }); }); diff --git a/src/packages/utils/src/things/json-rpc/json-rpc-base-types.ts b/src/packages/utils/src/things/json-rpc/json-rpc-base-types.ts index 1e91935e98..33963cf5f1 100644 --- a/src/packages/utils/src/things/json-rpc/json-rpc-base-types.ts +++ b/src/packages/utils/src/things/json-rpc/json-rpc-base-types.ts @@ -51,6 +51,7 @@ export class BaseJsonRpcType< case "string": { // handle hex-encoded string if ((value as string).indexOf("0x") === 0) { + toStrings.set(this, () => (value as string).toLowerCase().slice(2)); strCache.set(this, (value as string).toLowerCase()); toBuffers.set(this, () => { let fixedValue = (value as string).slice(2); diff --git a/src/packages/utils/src/things/json-rpc/json-rpc-data.ts b/src/packages/utils/src/things/json-rpc/json-rpc-data.ts index e0c06a4001..6ff153343f 100644 --- a/src/packages/utils/src/things/json-rpc/json-rpc-data.ts +++ b/src/packages/utils/src/things/json-rpc/json-rpc-data.ts @@ -2,40 +2,39 @@ import { BaseJsonRpcType } from "./json-rpc-base-types"; import { strCache, toStrings } from "./json-rpc-base-types"; function validateByteLength(byteLength?: number) { - if (typeof byteLength !== "number" || byteLength < 0) { - throw new Error(`byteLength must be a number greater than 0`); + if (typeof byteLength !== "number" || !(byteLength >= 0)) { + throw new Error(`byteLength must be a number greater than or equal to 0, provided: ${byteLength}`); } } -const byteLengths = new WeakMap(); + export class Data extends BaseJsonRpcType { - constructor(value: string | Buffer, byteLength?: number) { + + constructor(value: string | Buffer, private _byteLength?: number) { + super(value); if (typeof value === "bigint") { throw new Error(`Cannot create a ${typeof value} as a Data`); } - super(value); - if (byteLength !== void 0) { - validateByteLength(byteLength); - byteLengths.set(this, byteLength | 0); + if (_byteLength !== undefined) { + validateByteLength(_byteLength); } } public toString(byteLength?: number): string { - const str = strCache.get(this) as string; - if (str !== void 0) { - return str; + if (byteLength === undefined) { + byteLength = this._byteLength; + } + if (byteLength === undefined && strCache.has(this)) { + return strCache.get(this) as string; } else { let str = toStrings.get(this)() as string; let length = str.length; + if (length % 2 === 1) { length++; str = `0${str}`; } - if (byteLength !== void 0) { + if (byteLength !== undefined) { validateByteLength(byteLength); - } else { - byteLength = byteLengths.get(this); - } - if (byteLength !== void 0) { const strLength = byteLength * 2; const padBy = strLength - length; if (padBy < 0) { diff --git a/src/packages/utils/tests/json-rpc-data.test.ts b/src/packages/utils/tests/json-rpc-data.test.ts index d5f43a230b..0c4a73915d 100644 --- a/src/packages/utils/tests/json-rpc-data.test.ts +++ b/src/packages/utils/tests/json-rpc-data.test.ts @@ -2,7 +2,6 @@ import assert from "assert"; import {Data} from ".."; describe("json-rpc-data", () => { - describe("Data", () => { it("should stringify without specifying byteLength", () => { const cases = [ {input: "0x1", expected: "0x1"}, // I'm not sure whether this is the correct behaviour - should it return a single byte length string - ie 0x01? @@ -55,6 +54,7 @@ describe("json-rpc-data", () => { {input: "0x01", constructorLength: 1, expected: "0x01"}, {input: "0x01", constructorLength: 10, expected: "0x00000000000000000001"}, {input: "0x0123456789abcdef", constructorLength: 2, expected: "0x0123"}, + {input: "0x0123456789abcdef", constructorLength: 8, expected: "0x0123456789abcdef"}, {input: Buffer.from([0x01, 0x23]), constructorLength: 1, expected: "0x01"}, {input: Buffer.from([0x01]), constructorLength: 2, expected: "0x0001"} ]; @@ -63,7 +63,7 @@ describe("json-rpc-data", () => { const d = new Data(c.input, c.constructorLength); const stringified = d.toString(); - assert.equal(stringified, c.expected); + assert.equal(stringified, c.expected, `Expected "${stringified}" to be "${c.expected}", for input "${c.input}" and constructorLength ${c.constructorLength}`); }); }); @@ -84,13 +84,23 @@ describe("json-rpc-data", () => { }); }); + it("should stringify an empty value", () => { + const d = new Data("0x", 0); + const stringified = d.toString(0); + + assert.equal(stringified, "0x"); + }); + it("should fail with invalid byte lengths", () => { - const invalidByteLengths = [ -1, 0, "1", {}, [], null, NaN ]; // undefined is a valid value + const invalidByteLengths = [ -1, "1", {}, [], null, NaN ]; // undefined is a valid value - const d = new Data("0x01"); + invalidByteLengths.forEach(byteLength => { + const d = new Data("0x01"); + assert.throws(() => d.toString(byteLength), { message: `byteLength must be a number greater than or equal to 0, provided: ${byteLength}` }, `Invalid byteLength provided to toString: <${typeof byteLength}>: ${byteLength}`); + }); invalidByteLengths.forEach(byteLength => { - assert.throws(() => d.toString(byteLength), { message: "byteLength must be a number greater than 0" }, `Invalid bytelength provided: <${typeof byteLength}>: ${byteLength}`); + assert.throws(() => new Data("0x01", byteLength), { message: `byteLength must be a number greater than or equal to 0, provided: ${byteLength}` }, `Invalid byteLength provided to ctor: <${typeof byteLength}>: ${byteLength}`); }); }); }); From c99736f7029794e22d362306559687ecc7d26d7b Mon Sep 17 00:00:00 2001 From: Jeff Smale <6363749+jeffsmale90@users.noreply.github.com> Date: Tue, 29 Mar 2022 15:09:27 +1300 Subject: [PATCH 3/9] Rework tests to be more comprehensive --- .../ethereum/address/tests/index.test.ts | 30 +-- .../utils/tests/json-rpc-data.test.ts | 224 ++++++++++++------ 2 files changed, 168 insertions(+), 86 deletions(-) diff --git a/src/chains/ethereum/address/tests/index.test.ts b/src/chains/ethereum/address/tests/index.test.ts index 5c9a88d31f..0251283e3a 100644 --- a/src/chains/ethereum/address/tests/index.test.ts +++ b/src/chains/ethereum/address/tests/index.test.ts @@ -2,24 +2,26 @@ import assert from "assert"; import {Address} from "../"; describe("@ganache/ethereum-address", () => { - it("should pad an address to 20 bytes", () => { - const address = new Address("0x1"); - const stringifiedAddress = address.toString(); + describe("toString()", () => { + it("should pad an address to 20 bytes", () => { + const address = new Address("0x1"); + const stringifiedAddress = address.toString(); - assert.equal(stringifiedAddress, "0x0000000000000000000000000000000000000001"); - }); + assert.equal(stringifiedAddress, "0x0000000000000000000000000000000000000001"); + }); - it("should pad an address to the specified length", () => { - const address = new Address("0x1"); - const stringifiedAddress = address.toString(1); + it("should truncate an address to the specified length", () => { + const address = new Address("0x1"); + const stringifiedAddress = address.toString(1); - assert.equal(stringifiedAddress, "0x01"); - }); + assert.equal(stringifiedAddress, "0x01"); + }); - it("should create an address from a 20 byte address string", () => { - const address = new Address("0x2104859394604359378433865360947116707876"); - const stringifiedAddress = address.toString(); + it("should stringify a 20 byte address string", () => { + const address = new Address("0x2104859394604359378433865360947116707876"); + const stringifiedAddress = address.toString(); - assert.equal(stringifiedAddress, "0x2104859394604359378433865360947116707876"); + assert.equal(stringifiedAddress, "0x2104859394604359378433865360947116707876"); + }); }); }); diff --git a/src/packages/utils/tests/json-rpc-data.test.ts b/src/packages/utils/tests/json-rpc-data.test.ts index 0c4a73915d..078bf2b99e 100644 --- a/src/packages/utils/tests/json-rpc-data.test.ts +++ b/src/packages/utils/tests/json-rpc-data.test.ts @@ -2,106 +2,186 @@ import assert from "assert"; import {Data} from ".."; describe("json-rpc-data", () => { - it("should stringify without specifying byteLength", () => { - const cases = [ - {input: "0x1", expected: "0x1"}, // I'm not sure whether this is the correct behaviour - should it return a single byte length string - ie 0x01? - {input: "0x01", expected: "0x01"}, - {input: "0x0123456789abcdef", expected: "0x0123456789abcdef"}, - {input: Buffer.from([0x01]), expected: "0x01"} - ]; - - cases.forEach(c => { - const d = new Data(c.input); - const stringified = d.toString(); - - assert.equal(stringified, c.expected); + const validValues = [ "0x", "0x1", "0x1234", Buffer.from([]), Buffer.from([0x12,0x34]) ]; + const invalidValues: any[] = [ "1234", 1234n, NaN/*, undefined, null, 1234, [], {}, "0x-1234"*/ ]; // todo: this should be addressed in rewrite of json-rpc-data + // See related https://github.com/trufflesuite/ganache/issues/2728 + const validBytelengths = (() => { let i = 0; return [...new Array(100)].map(_ => i++); })(); // [0...99] + const invalidBytelengths: any[] = [ -1, "1", {}, [], null, NaN ]; + const inputOf32Bytes = "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"; + + function getExpectedString(value: Buffer|string, bytelength?: number) { + let expected: string; + + if (typeof value === "string") { + expected = value.slice(2); + } else if (Buffer.isBuffer(value)) { + expected = (value).toString("hex"); + } else { + throw new Error(`Type not supported ${typeof value}`) + } + if (bytelength !== undefined) { + const padCharCount = (bytelength - expected.length / 2) * 2; // (desired byte count - actual byte count) * 2 characters per byte + if (padCharCount > 0) { + expected = "0".repeat(padCharCount) + expected; + } else { + expected = expected.slice(Math.abs(padCharCount)); + } + } + return "0x" + expected; + } + + describe("ctor", () => { + it("should accept different values", () => { + validValues.forEach(value => { + const d = new Data(value); }); }); - it("should stringify to fixed byteLength", () => { - const cases = [ - {input: "0x1", length: 1, expected: "0x01"}, - {input: "0x01", length: 2, expected: "0x0001"}, - {input: "0x01", length: 10, expected: "0x00000000000000000001"}, - {input: Buffer.from([0x01]), length: 2, expected: "0x0001"} - ]; + it("should fail with invalid values", () => { + invalidValues.forEach(value => { + assert.throws(() => { + const d = new Data(value); + }, undefined, `Should fail to accept value: ${value} of type: ${typeof value}`); + }); + }); - cases.forEach(c => { - const d = new Data(c.input); - const stringified = d.toString(c.length); + it("should accept valid bytelengths", () => { + validBytelengths.forEach(bytelength => { + const d = new Data("0x01", bytelength); + }); + }); - assert.equal(stringified, c.expected); + it("should fail with invalid bytelengths", () => { + invalidBytelengths.forEach(bytelength => { + assert.throws(() => { + const d = new Data("0x01", bytelength); + }, undefined, `Should fail to accept bytelength: ${bytelength} of type: ${typeof bytelength}`); }); }); + }); - it("should stringify and truncate to a shorter byteLength", () => { - const cases = [ - {input: "0x0123", length: 1, expected: "0x01"}, - {input: "0x0123456789abcdef", length: 2, expected: "0x0123"}, - {input: Buffer.from([0x01, 0x23]), length: 1, expected: "0x01"} - ]; + describe("from()", () => { + it("should accept different representations of value", () => { + validValues.forEach(value => { + const d = Data.from(value); + }); + }); - cases.forEach(c => { - const d = new Data(c.input); - const stringified = d.toString(c.length); + it("should fail with invalid values", () => { + invalidValues.forEach(value => { + assert.throws(() => { + const d = Data.from(value); + }, undefined, `Should fail to accept value: ${value} of type: ${typeof value}`); + }); + }); - assert.equal(stringified, c.expected); + it("should accept valid bytelengths", () => { + validBytelengths.forEach(bytelength => { + const d = Data.from("0x01", bytelength); }); }); - it("should stringify to the byteLength specified in the constructor", () => { - const cases = [ - {input: "0x01", constructorLength: 1, expected: "0x01"}, - {input: "0x01", constructorLength: 10, expected: "0x00000000000000000001"}, - {input: "0x0123456789abcdef", constructorLength: 2, expected: "0x0123"}, - {input: "0x0123456789abcdef", constructorLength: 8, expected: "0x0123456789abcdef"}, - {input: Buffer.from([0x01, 0x23]), constructorLength: 1, expected: "0x01"}, - {input: Buffer.from([0x01]), constructorLength: 2, expected: "0x0001"} - ]; + it("should fail with invalid bytelengths", () => { + invalidBytelengths.forEach(bytelength => { + assert.throws(() => { + const d = Data.from("0x01", bytelength); + }, undefined, `Should fail to accept bytelength: ${bytelength} of type: ${typeof bytelength}`); + }); + }); + }); - cases.forEach(c => { - const d = new Data(c.input, c.constructorLength); - const stringified = d.toString(); + describe("toString()", () => { + it("should stringify without arguments", () => { + validValues.forEach(value => { + const d = new Data(value); + const s = d.toString(); + const expected = getExpectedString(value); - assert.equal(stringified, c.expected, `Expected "${stringified}" to be "${c.expected}", for input "${c.input}" and constructorLength ${c.constructorLength}`); + assert.equal(s, expected); }); }); - it("should stringify to the byteLength specified in toString, over the byteLength specified in the constructor", () => { - const cases = [ - {input: "0x01", constructorLength: 2, length: 1, expected: "0x01"}, - {input: "0x01", constructorLength: 1, length: 10, expected: "0x00000000000000000001"}, - {input: "0x0123456789abcdef", constructorLength: 1, length: 2, expected: "0x0123"}, - {input: Buffer.from([0x01, 0x23]), constructorLength: 2, length: 1, expected: "0x01"}, - {input: Buffer.from([0x01]), constructorLength: 1, length: 2, expected: "0x0001"} - ]; + it("should stringify with valid bytelengths", () => { + validValues.forEach(value => { + const d = new Data(value); + validBytelengths.forEach(bytelength => { + const s = d.toString(bytelength); + const expected = getExpectedString(s, bytelength); - cases.forEach(c => { - const d = new Data(c.input, c.constructorLength); - const stringified = d.toString(c.length); + assert.equal(s, expected); + }); + }); + }); - assert.equal(stringified, c.expected); + it("should fail with invalid bytelengths", () => { + validValues.forEach(value => { + const d = new Data(value); + invalidBytelengths.forEach(bytelength => { + assert.throws(() => { + const s = d.toString(bytelength); + }, undefined, `Should fail to accept bytelength: ${bytelength} of type: ${typeof bytelength}`); + }); }); }); - it("should stringify an empty value", () => { - const d = new Data("0x", 0); - const stringified = d.toString(0); + it("should pad the value with larger bytelength", () => { + validValues.forEach(value => { + const d = new Data(value); + const s = d.toString(10); + const expected = getExpectedString(s, 10); - assert.equal(stringified, "0x"); + assert.equal(s, expected); + }); }); - it("should fail with invalid byte lengths", () => { - const invalidByteLengths = [ -1, "1", {}, [], null, NaN ]; // undefined is a valid value + it("should truncate the value with a smaller bytelength", () => { + const d = new Data("0x1234567890abcdef"); + const s = d.toString(2); - invalidByteLengths.forEach(byteLength => { - const d = new Data("0x01"); - assert.throws(() => d.toString(byteLength), { message: `byteLength must be a number greater than or equal to 0, provided: ${byteLength}` }, `Invalid byteLength provided to toString: <${typeof byteLength}>: ${byteLength}`); - }); + assert.equal(s, "0x1234"); + }); - invalidByteLengths.forEach(byteLength => { - assert.throws(() => new Data("0x01", byteLength), { message: `byteLength must be a number greater than or equal to 0, provided: ${byteLength}` }, `Invalid byteLength provided to ctor: <${typeof byteLength}>: ${byteLength}`); - }); + it("should truncate with a large value", () => { + const expectedStringLength = 62; // 30 bytes x 2 characters per byte + 2 for 0x prefix + const d = new Data(inputOf32Bytes); + const s = d.toString(30); + + assert.equal(s, inputOf32Bytes.slice(0, expectedStringLength)); + }); + + it("should pad with a large value", () => { + const d = new Data(inputOf32Bytes); + const s = d.toString(34); // 2 additional bytes, ie "0000" + + assert.equal(s, "0x0000" + inputOf32Bytes.slice(2)); + }); + }); + + describe("toBuffer()", () => { + it("should create a buffer", () => { + const expected = Buffer.from([0x12, 0x34]); + const d = new Data("0x1234"); + const b = d.toBuffer(); + + assert.deepEqual(b, expected); + }); + + // todo: this should be addressed in rewrite of json-rpc-data + it.skip("should create a buffer with a smaller bytelength", () => { + const expected = Buffer.from([0x12, 0x34]); + const d = new Data("0x123456789abcdef", 2); + const b = d.toBuffer(); + + assert.deepEqual(b, expected); + }); + + // todo: this should be addressed in rewrite of json-rpc-data + it.skip("should create a buffer with a larger bytelength", () => { + const expected = Buffer.from([0x00, 0x00, 0x12, 0x34]); + const d = new Data("0x1234", 4); + const b = d.toBuffer(); + + assert.deepEqual(b, expected); }); }); }); From 79f8661089cb6f83249933c57c4d5b2e9eda9438 Mon Sep 17 00:00:00 2001 From: jeffsmale90 <6363749+jeffsmale90@users.noreply.github.com> Date: Thu, 31 Mar 2022 16:40:34 +1300 Subject: [PATCH 4/9] change reference to related issue to point to a label Co-authored-by: Micaiah Reid --- src/packages/utils/tests/json-rpc-data.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/packages/utils/tests/json-rpc-data.test.ts b/src/packages/utils/tests/json-rpc-data.test.ts index 078bf2b99e..cfda2dc9d8 100644 --- a/src/packages/utils/tests/json-rpc-data.test.ts +++ b/src/packages/utils/tests/json-rpc-data.test.ts @@ -4,7 +4,7 @@ import {Data} from ".."; describe("json-rpc-data", () => { const validValues = [ "0x", "0x1", "0x1234", Buffer.from([]), Buffer.from([0x12,0x34]) ]; const invalidValues: any[] = [ "1234", 1234n, NaN/*, undefined, null, 1234, [], {}, "0x-1234"*/ ]; // todo: this should be addressed in rewrite of json-rpc-data - // See related https://github.com/trufflesuite/ganache/issues/2728 + // See related https://github.com/trufflesuite/ganache/labels/json-rpc%20refactor const validBytelengths = (() => { let i = 0; return [...new Array(100)].map(_ => i++); })(); // [0...99] const invalidBytelengths: any[] = [ -1, "1", {}, [], null, NaN ]; const inputOf32Bytes = "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"; From 70851fc855551fc2320861a202fc6c5b8d72bdd3 Mon Sep 17 00:00:00 2001 From: jeffsmale90 <6363749+jeffsmale90@users.noreply.github.com> Date: Thu, 31 Mar 2022 16:41:02 +1300 Subject: [PATCH 5/9] expand ctor abbreviation to constructor Co-authored-by: Micaiah Reid --- src/packages/utils/tests/json-rpc-data.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/packages/utils/tests/json-rpc-data.test.ts b/src/packages/utils/tests/json-rpc-data.test.ts index cfda2dc9d8..eab6b41892 100644 --- a/src/packages/utils/tests/json-rpc-data.test.ts +++ b/src/packages/utils/tests/json-rpc-data.test.ts @@ -30,7 +30,7 @@ describe("json-rpc-data", () => { return "0x" + expected; } - describe("ctor", () => { + describe("constructor", () => { it("should accept different values", () => { validValues.forEach(value => { const d = new Data(value); From 5f624dd52df4f499285dee178131029b36aee9a1 Mon Sep 17 00:00:00 2001 From: jeffsmale90 <6363749+jeffsmale90@users.noreply.github.com> Date: Thu, 31 Mar 2022 16:41:37 +1300 Subject: [PATCH 6/9] add link to label in code Co-authored-by: Micaiah Reid --- src/packages/utils/tests/json-rpc-data.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/packages/utils/tests/json-rpc-data.test.ts b/src/packages/utils/tests/json-rpc-data.test.ts index eab6b41892..9359a77129 100644 --- a/src/packages/utils/tests/json-rpc-data.test.ts +++ b/src/packages/utils/tests/json-rpc-data.test.ts @@ -166,7 +166,7 @@ describe("json-rpc-data", () => { assert.deepEqual(b, expected); }); - // todo: this should be addressed in rewrite of json-rpc-data + // todo: this should be addressed in rewrite of json-rpc-data https://github.com/trufflesuite/ganache/labels/json-rpc%20refactor it.skip("should create a buffer with a smaller bytelength", () => { const expected = Buffer.from([0x12, 0x34]); const d = new Data("0x123456789abcdef", 2); From f2269ca2b111e2fea16cacab06adfb93a7961a7e Mon Sep 17 00:00:00 2001 From: jeffsmale90 <6363749+jeffsmale90@users.noreply.github.com> Date: Thu, 31 Mar 2022 16:41:50 +1300 Subject: [PATCH 7/9] add link to label in code Co-authored-by: Micaiah Reid --- src/packages/utils/tests/json-rpc-data.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/packages/utils/tests/json-rpc-data.test.ts b/src/packages/utils/tests/json-rpc-data.test.ts index 9359a77129..ec85610273 100644 --- a/src/packages/utils/tests/json-rpc-data.test.ts +++ b/src/packages/utils/tests/json-rpc-data.test.ts @@ -175,7 +175,7 @@ describe("json-rpc-data", () => { assert.deepEqual(b, expected); }); - // todo: this should be addressed in rewrite of json-rpc-data + // todo: this should be addressed in rewrite of json-rpc-data https://github.com/trufflesuite/ganache/labels/json-rpc%20refactor it.skip("should create a buffer with a larger bytelength", () => { const expected = Buffer.from([0x00, 0x00, 0x12, 0x34]); const d = new Data("0x1234", 4); From 48a010350cb822ced055fd46e256ec6c18b71c75 Mon Sep 17 00:00:00 2001 From: Jeff Smale <6363749+jeffsmale90@users.noreply.github.com> Date: Thu, 31 Mar 2022 17:12:06 +1300 Subject: [PATCH 8/9] fix issue with expected string generator, remove special cases tests, and explain the cases in getExpectedString --- .../utils/tests/json-rpc-data.test.ts | 47 +++++++------------ 1 file changed, 17 insertions(+), 30 deletions(-) diff --git a/src/packages/utils/tests/json-rpc-data.test.ts b/src/packages/utils/tests/json-rpc-data.test.ts index ec85610273..204c13844d 100644 --- a/src/packages/utils/tests/json-rpc-data.test.ts +++ b/src/packages/utils/tests/json-rpc-data.test.ts @@ -2,12 +2,12 @@ import assert from "assert"; import {Data} from ".."; describe("json-rpc-data", () => { - const validValues = [ "0x", "0x1", "0x1234", Buffer.from([]), Buffer.from([0x12,0x34]) ]; + const inputOf32Bytes = "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"; + const validValues = [ "0x", "0x1", "0x1234", Buffer.from([]), Buffer.from([0x12,0x34]), inputOf32Bytes ]; const invalidValues: any[] = [ "1234", 1234n, NaN/*, undefined, null, 1234, [], {}, "0x-1234"*/ ]; // todo: this should be addressed in rewrite of json-rpc-data // See related https://github.com/trufflesuite/ganache/labels/json-rpc%20refactor const validBytelengths = (() => { let i = 0; return [...new Array(100)].map(_ => i++); })(); // [0...99] const invalidBytelengths: any[] = [ -1, "1", {}, [], null, NaN ]; - const inputOf32Bytes = "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"; function getExpectedString(value: Buffer|string, bytelength?: number) { let expected: string; @@ -20,11 +20,18 @@ describe("json-rpc-data", () => { throw new Error(`Type not supported ${typeof value}`) } if (bytelength !== undefined) { + /* + If the value is longer than the specified bytelength, then the result my be left padded. + ie: "0x01" bytelength 2 becomes "0x0001" + + If the value is longer than the specified bytelength, then the result must be truncated. + ie: "0x123456" bytelength 2 becomes "0x1234" + */ const padCharCount = (bytelength - expected.length / 2) * 2; // (desired byte count - actual byte count) * 2 characters per byte if (padCharCount > 0) { expected = "0".repeat(padCharCount) + expected; } else { - expected = expected.slice(Math.abs(padCharCount)); + expected = expected.slice(0, bytelength * 2); } } return "0x" + expected; @@ -124,37 +131,17 @@ describe("json-rpc-data", () => { }); }); - it("should pad the value with larger bytelength", () => { + it("should stringify with valid bytelengths provided to constructor", () => { validValues.forEach(value => { - const d = new Data(value); - const s = d.toString(10); - const expected = getExpectedString(s, 10); + validBytelengths.forEach(bytelength => { + const d = new Data(value, bytelength); + const s = d.toString(); + const expected = getExpectedString(s, bytelength); - assert.equal(s, expected); + assert.equal(s, expected); + }); }); }); - - it("should truncate the value with a smaller bytelength", () => { - const d = new Data("0x1234567890abcdef"); - const s = d.toString(2); - - assert.equal(s, "0x1234"); - }); - - it("should truncate with a large value", () => { - const expectedStringLength = 62; // 30 bytes x 2 characters per byte + 2 for 0x prefix - const d = new Data(inputOf32Bytes); - const s = d.toString(30); - - assert.equal(s, inputOf32Bytes.slice(0, expectedStringLength)); - }); - - it("should pad with a large value", () => { - const d = new Data(inputOf32Bytes); - const s = d.toString(34); // 2 additional bytes, ie "0000" - - assert.equal(s, "0x0000" + inputOf32Bytes.slice(2)); - }); }); describe("toBuffer()", () => { From 2a552d1dae0084558026a0900f4a7893523a61fd Mon Sep 17 00:00:00 2001 From: jeffsmale90 <6363749+jeffsmale90@users.noreply.github.com> Date: Fri, 1 Apr 2022 09:24:06 +1300 Subject: [PATCH 9/9] fix typo in server tests (my=>must) Co-authored-by: Micaiah Reid --- src/packages/utils/tests/json-rpc-data.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/packages/utils/tests/json-rpc-data.test.ts b/src/packages/utils/tests/json-rpc-data.test.ts index 204c13844d..4f50f736c8 100644 --- a/src/packages/utils/tests/json-rpc-data.test.ts +++ b/src/packages/utils/tests/json-rpc-data.test.ts @@ -21,7 +21,7 @@ describe("json-rpc-data", () => { } if (bytelength !== undefined) { /* - If the value is longer than the specified bytelength, then the result my be left padded. + If the value is longer than the specified bytelength, then the result must be left padded. ie: "0x01" bytelength 2 becomes "0x0001" If the value is longer than the specified bytelength, then the result must be truncated.