Skip to content
This repository has been archived by the owner on Feb 26, 2024. It is now read-only.

Commit

Permalink
Rework tests to be more comprehensive
Browse files Browse the repository at this point in the history
  • Loading branch information
jeffsmale90 committed Mar 30, 2022
1 parent cd833af commit c9b50bc
Show file tree
Hide file tree
Showing 3 changed files with 169 additions and 87 deletions.
30 changes: 16 additions & 14 deletions src/chains/ethereum/address/tests/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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");
});
});
});
2 changes: 1 addition & 1 deletion src/packages/utils/src/things/json-rpc/json-rpc-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export class Data extends BaseJsonRpcType {

constructor(value: string | Buffer, private _byteLength?: number) {
super(value);
if (typeof value === "bigint") {
if (typeof value !== "string" && !Buffer.isBuffer(value)) {
throw new Error(`Cannot create a ${typeof value} as a Data`);
}
if (_byteLength !== undefined) {
Expand Down
224 changes: 152 additions & 72 deletions src/packages/utils/tests/json-rpc-data.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 , 1234, null, NaN, undefined, [], {}/*, "0x-1234"*/ ]; //todo: this should be addressed in rewrite of json-rpc-data
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 = (<Buffer>value).toString("hex");
} else {
throw new Error(`Type not supported ${typeof value}`)
}
if (bytelength !== undefined) {
const padCharCount = (bytelength - expected.length) * 2;
if (padCharCount > 0) {
expected = "0".repeat(padCharCount);
} else {
expected = expected.slice(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(<any>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(<any>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", <any>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);
});
});
});

0 comments on commit c9b50bc

Please sign in to comment.