Added more tests
This commit is contained in:
parent
8049071152
commit
b30597c686
@ -6,7 +6,7 @@ import {
|
|||||||
InfuraProvider,
|
InfuraProvider,
|
||||||
// PocketProvider,
|
// PocketProvider,
|
||||||
|
|
||||||
// FallbackProvider,
|
FallbackProvider,
|
||||||
isError,
|
isError,
|
||||||
} from "../index.js";
|
} from "../index.js";
|
||||||
|
|
||||||
@ -79,23 +79,19 @@ const ProviderCreators: Array<ProviderCreator> = [
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
*/
|
*/
|
||||||
/*
|
|
||||||
{
|
{
|
||||||
name: "FallbackProvider",
|
name: "FallbackProvider",
|
||||||
networks: ethNetworks,
|
networks: ethNetworks,
|
||||||
create: function(network: string) {
|
create: function(network: string) {
|
||||||
const providers: Array<AbstractProvider> = [];
|
const providers: Array<AbstractProvider> = [];
|
||||||
for (const creator of ProviderCreators) {
|
for (const providerName of [ "AlchemyProvider", "AnkrProvider", "EtherscanProvider", "InfuraProvider" ]) {
|
||||||
if (creator.name === "FallbackProvider") { continue; }
|
const provider = getProvider(providerName, network);
|
||||||
if (creator.networks.indexOf(network) >= 0) {
|
|
||||||
const provider = creator.create(network);
|
|
||||||
if (provider) { providers.push(provider); }
|
if (provider) { providers.push(provider); }
|
||||||
}
|
}
|
||||||
}
|
if (providers.length === 0) { throw new Error("UNSUPPORTED NETWORK"); }
|
||||||
return new FallbackProvider(providers);
|
return new FallbackProvider(providers);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
*/
|
|
||||||
];
|
];
|
||||||
|
|
||||||
export const providerNames = Object.freeze(ProviderCreators.map((c) => (c.name)));
|
export const providerNames = Object.freeze(ProviderCreators.map((c) => (c.name)));
|
||||||
|
@ -1,40 +1,181 @@
|
|||||||
/*
|
|
||||||
import assert from "assert";
|
import assert from "assert";
|
||||||
|
|
||||||
import { connect } from "./create-provider.js";
|
import { getProvider } from "./create-provider.js";
|
||||||
|
|
||||||
import { Contract } from "../index.js";
|
import { Contract, EventLog, Wallet } from "../index.js";
|
||||||
|
import type { ContractEventPayload, ContractEventName, Log } from "../index.js";
|
||||||
|
|
||||||
describe("Test Contract", function() {
|
describe("Test Contract", function() {
|
||||||
it("tests contract @TODO: expand", async function() {
|
const addr = "0x99417252Aad7B065940eBdF50d665Fb8879c5958";
|
||||||
const provider = connect("mainnet");
|
const abi = [
|
||||||
|
"error CustomError1(uint256 code, string message)",
|
||||||
|
|
||||||
const contract = new Contract("dai.tokens.ethers.eth", [
|
"event EventUint256(uint256 indexed value)",
|
||||||
"function balanceOf(address) view returns (uint)"
|
"event EventAddress(address indexed value)",
|
||||||
], provider);
|
"event EventString(string value)",
|
||||||
|
"event EventBytes(bytes value)",
|
||||||
|
|
||||||
assert.equal(await contract.balanceOf("ricmoo.firefly.eth"), BigInt("6015089439794538201631"));
|
"function testCustomError1(bool pass, uint code, string calldata message) pure returns (uint256)",
|
||||||
|
"function testErrorString(bool pass, string calldata message) pure returns (uint256)",
|
||||||
|
"function testPanic(uint256 code) returns (uint256)",
|
||||||
|
"function testEvent(uint256 valueUint256, address valueAddress, string valueString, bytes valueBytes) public",
|
||||||
|
"function testCallAdd(uint256 a, uint256 b) pure returns (uint256 result)"
|
||||||
|
];
|
||||||
|
|
||||||
|
it("tests contract calls", async function() {
|
||||||
|
this.timeout(10000);
|
||||||
|
|
||||||
|
const provider = getProvider("InfuraProvider", "goerli");
|
||||||
|
const contract = new Contract(addr, abi, provider);
|
||||||
|
|
||||||
|
assert.equal(await contract.testCallAdd(4, 5), BigInt(9), "testCallAdd(4, 5)");
|
||||||
|
assert.equal(await contract.testCallAdd(6, 0), BigInt(6), "testCallAdd(6, 0)");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("tests events", async function() {
|
||||||
|
this.timeout(60000);
|
||||||
|
|
||||||
|
const provider = getProvider("InfuraProvider", "goerli");
|
||||||
|
assert.ok(provider);
|
||||||
|
|
||||||
|
const contract = new Contract(addr, abi, provider);
|
||||||
|
|
||||||
|
const signer = new Wallet(<string>(process.env.FAUCET_PRIVATEKEY), provider);
|
||||||
|
const contractSigner = <any>contract.connect(signer);
|
||||||
|
|
||||||
|
const vUint256 = 42;
|
||||||
|
const vAddrName = "ethers.eth";
|
||||||
|
const vAddr = "0x228568EA92aC5Bc281c1E30b1893735c60a139F1";
|
||||||
|
const vString = "Hello";
|
||||||
|
const vBytes = "0x12345678";
|
||||||
|
|
||||||
|
let hash: null | string = null;
|
||||||
|
|
||||||
|
// Test running a listener for a specific event
|
||||||
|
const specificEvent = new Promise((resolve, reject) => {
|
||||||
|
contract.on("EventUint256", async (value, event) => {
|
||||||
|
// Triggered by someone else
|
||||||
|
if (hash == null || hash !== event.log.transactionHash) { return; }
|
||||||
|
|
||||||
|
try {
|
||||||
|
assert.equal(event.filter, "EventUint256", "event.filter");
|
||||||
|
assert.equal(event.fragment.name, "EventUint256", "event.fragment.name");
|
||||||
|
assert.equal(event.log.address, addr, "event.log.address");
|
||||||
|
assert.equal(event.args.length, 1, "event.args.length");
|
||||||
|
assert.equal(event.args[0], BigInt(42), "event.args[0]");
|
||||||
|
|
||||||
|
const count = await contract.listenerCount("EventUint256");
|
||||||
|
await event.removeListener();
|
||||||
|
assert.equal(await contract.listenerCount("EventUint256"), count - 1, "decrement event count");
|
||||||
|
|
||||||
|
resolve(null);
|
||||||
|
} catch (e) {
|
||||||
|
event.removeListener();
|
||||||
|
reject(e);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
*/
|
|
||||||
/*
|
|
||||||
import { Typed } from "../abi/index.js";
|
|
||||||
import * as providers from "../providers/index.js";
|
|
||||||
|
|
||||||
import { Contract } from "../index.js";
|
// Test running a listener on all (i.e. "*") events
|
||||||
|
const allEvents = new Promise((resolve, reject) => {
|
||||||
|
const waitingFor: Record<string, any> = {
|
||||||
|
EventUint256: vUint256,
|
||||||
|
EventAddress: vAddr,
|
||||||
|
EventString: vString,
|
||||||
|
EventBytes: vBytes
|
||||||
|
};
|
||||||
|
|
||||||
import { log } from "./utils.js";
|
contract.on("*", (event: ContractEventPayload) => {
|
||||||
*/
|
// Triggered by someone else
|
||||||
//import type { Addressable } from "@ethersproject/address";
|
if (hash == null || hash !== event.log.transactionHash) { return; }
|
||||||
//import type { BigNumberish } from "@ethersproject/logger";
|
try {
|
||||||
|
const name = event.eventName;
|
||||||
|
|
||||||
|
assert.equal(event.args[0], waitingFor[name], `${ name }`);
|
||||||
|
delete waitingFor[name];
|
||||||
|
|
||||||
|
if (Object.keys(waitingFor).length === 0) {
|
||||||
|
event.removeListener();
|
||||||
|
resolve(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
// Send a transaction to trigger some events
|
||||||
|
const tx = await contractSigner.testEvent(vUint256, vAddr, vString, vBytes);
|
||||||
|
hash = tx.hash;
|
||||||
|
|
||||||
|
const checkEvent = (filter: ContractEventName, event: EventLog | Log) => {
|
||||||
|
const values: Record<string, any> = {
|
||||||
|
EventUint256: vUint256,
|
||||||
|
EventString: vString,
|
||||||
|
EventAddress: vAddr,
|
||||||
|
EventBytes: vBytes
|
||||||
|
};
|
||||||
|
|
||||||
|
assert.ok(event instanceof EventLog, `queryFilter(${ filter }):isEventLog`);
|
||||||
|
|
||||||
|
const name = event.eventName;
|
||||||
|
|
||||||
|
assert.equal(event.address, addr, `queryFilter(${ filter }):address`);
|
||||||
|
assert.equal(event.args[0], values[name], `queryFilter(${ filter }):args[0]`);
|
||||||
|
};
|
||||||
|
|
||||||
|
const checkEventFilter = async (filter: ContractEventName) => {
|
||||||
|
const events = (await contract.queryFilter(filter, -10)).filter((e) => (e.transactionHash === hash));
|
||||||
|
assert.equal(events.length, 1, `queryFilter(${ filter }).length`);
|
||||||
|
checkEvent(filter, events[0]);
|
||||||
|
return events[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
const receipt = await tx.wait();
|
||||||
|
|
||||||
|
// Check the logs in the receipt
|
||||||
|
for (const log of receipt.logs) { checkEvent("receipt", log); }
|
||||||
|
|
||||||
|
// Various options for queryFilter
|
||||||
|
await checkEventFilter("EventUint256");
|
||||||
|
await checkEventFilter([ "EventUint256" ]);
|
||||||
|
await checkEventFilter([ [ "EventUint256" ] ]);
|
||||||
|
await checkEventFilter("EventUint256(uint)");
|
||||||
|
await checkEventFilter([ "EventUint256(uint)" ]);
|
||||||
|
await checkEventFilter([ [ "EventUint256(uint)" ] ]);
|
||||||
|
await checkEventFilter([ [ "EventUint256", "EventUint256(uint)" ] ]);
|
||||||
|
await checkEventFilter("0x85c55bbb820e6d71c71f4894e57751de334b38c421f9c170b0e66d32eafea337");
|
||||||
|
|
||||||
|
// Query by Event
|
||||||
|
await checkEventFilter(contract.filters.EventUint256);
|
||||||
|
|
||||||
|
// Query by Deferred Topic Filter; address
|
||||||
|
await checkEventFilter(contract.filters.EventUint256(vUint256));
|
||||||
|
|
||||||
|
// Query by Deferred Topic Filter; address
|
||||||
|
await checkEventFilter(contract.filters.EventAddress(vAddr));
|
||||||
|
|
||||||
|
// Query by Deferred Topic Filter; ENS name => address
|
||||||
|
await checkEventFilter(contract.filters.EventAddress(vAddrName));
|
||||||
|
|
||||||
|
// Multiple Methods
|
||||||
|
{
|
||||||
|
const filter = [ [ "EventUint256", "EventString" ] ];
|
||||||
|
const events = (await contract.queryFilter(filter, -10)).filter((e) => (e.transactionHash === hash));
|
||||||
|
assert.equal(events.length, 2, `queryFilter(${ filter }).length`);
|
||||||
|
|
||||||
|
for (const event of events) { checkEvent(filter, event); }
|
||||||
|
}
|
||||||
|
|
||||||
|
await specificEvent;
|
||||||
|
await allEvents;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
/*
|
|
||||||
import type {
|
|
||||||
ConstantContractMethod, ContractMethod, ContractEvent
|
|
||||||
} from "../index.js";
|
|
||||||
*/
|
|
||||||
|
|
||||||
// @TODO
|
|
||||||
/*
|
/*
|
||||||
describe("Test Contract Calls", function() {
|
describe("Test Contract Calls", function() {
|
||||||
it("finds typed methods", async function() {
|
it("finds typed methods", async function() {
|
||||||
@ -48,8 +189,7 @@ describe("Test Contract Calls", function() {
|
|||||||
contract["foo(string)"].fragment
|
contract["foo(string)"].fragment
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
*/
|
|
||||||
/*
|
|
||||||
describe("Test Contract Interface", function() {
|
describe("Test Contract Interface", function() {
|
||||||
it("builds contract interfaces", async function() {
|
it("builds contract interfaces", async function() {
|
||||||
this.timeout(60000);
|
this.timeout(60000);
|
||||||
@ -105,14 +245,3 @@ describe("Test Contract Interface", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
*/
|
*/
|
||||||
/*
|
|
||||||
describe("Test Contract Calls", function() {
|
|
||||||
it("calls ERC-20 methods", async function() {
|
|
||||||
const provider = new providers.AnkrProvider();
|
|
||||||
const contract = new Contract("0xC18360217D8F7Ab5e7c516566761Ea12Ce7F9D72", [
|
|
||||||
"function balanceOf(address owner) view returns (uint)",
|
|
||||||
], provider);
|
|
||||||
log(this, `balance: ${ await contract.balanceOf("0x5555763613a12D8F3e73be831DFf8598089d3dCa") }`);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
|
@ -2,7 +2,8 @@ import assert from "assert";
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
hashMessage,
|
hashMessage,
|
||||||
solidityPackedKeccak256, solidityPackedSha256
|
solidityPacked, solidityPackedKeccak256, solidityPackedSha256,
|
||||||
|
isError
|
||||||
} from "../index.js";
|
} from "../index.js";
|
||||||
|
|
||||||
import { loadTests } from "./utils.js"
|
import { loadTests } from "./utils.js"
|
||||||
@ -157,4 +158,21 @@ describe("Test Solidity Hash functions", function() {
|
|||||||
assert.equal(solidityPackedSha256(test.types, test.values), test.sha256);
|
assert.equal(solidityPackedSha256(test.types, test.values), test.sha256);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
|
||||||
|
const badTypes = [
|
||||||
|
{ types: [ "uint5" ], values: [ 1 ] },
|
||||||
|
{ types: [ "bytes0" ], values: [ "0x" ] },
|
||||||
|
{ types: [ "blorb" ], values: [ false ] },
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const { types, values } of badTypes) {
|
||||||
|
it("fails on invalid type", function() {
|
||||||
|
assert.throws(function() {
|
||||||
|
const result = solidityPacked(types, values);
|
||||||
|
console.log(result);
|
||||||
|
}, function (error) {
|
||||||
|
return (isError(error, "INVALID_ARGUMENT") && error.argument === "type");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
48
src.ts/_tests/test-providers-send.ts
Normal file
48
src.ts/_tests/test-providers-send.ts
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import assert from "assert";
|
||||||
|
|
||||||
|
import { Wallet } from "../index.js";
|
||||||
|
|
||||||
|
import { getProvider, providerNames } from "./create-provider.js";
|
||||||
|
|
||||||
|
|
||||||
|
describe("Sends Transactions", function() {
|
||||||
|
|
||||||
|
const cleanup: Array<() => void> = [ ];
|
||||||
|
after(function() {
|
||||||
|
for (const func of cleanup) { func(); }
|
||||||
|
});
|
||||||
|
|
||||||
|
const wallet = new Wallet(<string>(process.env.FAUCET_PRIVATEKEY));
|
||||||
|
|
||||||
|
const networkName = "goerli";
|
||||||
|
for (const providerName of providerNames) {
|
||||||
|
const provider = getProvider(providerName, networkName);
|
||||||
|
if (provider == null) { continue; }
|
||||||
|
|
||||||
|
// Shutdown socket-based provider, otherwise its socket will prevent
|
||||||
|
// this process from exiting
|
||||||
|
if ((<any>provider).destroy) { cleanup.push(() => { (<any>provider).destroy(); }); }
|
||||||
|
|
||||||
|
it(`tests sending: ${ providerName }.`, async function() {
|
||||||
|
this.timeout(60000);
|
||||||
|
|
||||||
|
const w = wallet.connect(provider);
|
||||||
|
|
||||||
|
const dustAddr = Wallet.createRandom().address;
|
||||||
|
|
||||||
|
const tx = await w.sendTransaction({
|
||||||
|
to: dustAddr,
|
||||||
|
value: 42,
|
||||||
|
type: 2
|
||||||
|
});
|
||||||
|
|
||||||
|
const receipt = await provider.waitForTransaction(tx.hash); //tx.wait();
|
||||||
|
console.log(receipt);
|
||||||
|
|
||||||
|
const balance = await provider.getBalance(dustAddr);
|
||||||
|
assert.equal(balance, BigInt(42), "target balance after send");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
});
|
73
src.ts/_tests/test-utils-units.ts
Normal file
73
src.ts/_tests/test-utils-units.ts
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
import assert from "assert";
|
||||||
|
|
||||||
|
import { loadTests } from "./utils.js";
|
||||||
|
|
||||||
|
import { formatEther, formatUnits, parseEther, parseUnits } from "../index.js";
|
||||||
|
|
||||||
|
import type { TestCaseUnit } from "./types.js";
|
||||||
|
|
||||||
|
|
||||||
|
describe("Tests unit conversion", function() {
|
||||||
|
const tests = loadTests<TestCaseUnit>("units");
|
||||||
|
|
||||||
|
const units = [
|
||||||
|
{ unit: "ether", format: "ether_format", decimals: 18 },
|
||||||
|
{ unit: "kwei", format: "kwei_format", decimals: 3 },
|
||||||
|
{ unit: "mwei", format: "mwei_format", decimals: 6 },
|
||||||
|
{ unit: "gwei", format: "gwei_format", decimals: 9 },
|
||||||
|
{ unit: "szabo", format: "szabo_format", decimals: 12 },
|
||||||
|
{ unit: "finney", format: "finney_format", decimals: 15 },
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const { unit, format, decimals } of units) {
|
||||||
|
|
||||||
|
for (const test of tests) {
|
||||||
|
const str = <string | null>((<any>test)[format]);
|
||||||
|
if (str == null) { continue; }
|
||||||
|
|
||||||
|
it(`converts wei to ${ unit } string: ${ test.name }`, function() {
|
||||||
|
const wei = BigInt(test.wei);
|
||||||
|
if (decimals === 18) {
|
||||||
|
assert.equal(formatEther(wei), str, "formatEther");
|
||||||
|
assert.equal(formatUnits(wei), str, "formatUnits");
|
||||||
|
}
|
||||||
|
assert.equal(formatUnits(wei, unit), str, `formatUnits(${ unit })`);
|
||||||
|
assert.equal(formatUnits(wei, decimals), str, `formatUnits(${ decimals })`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const test of tests) {
|
||||||
|
const str = <string | null>((<any>test)[format]);
|
||||||
|
if (str == null) { continue; }
|
||||||
|
|
||||||
|
it(`converts ${ format } string to wei: ${ test.name }`, function() {
|
||||||
|
const wei = BigInt(test.wei);
|
||||||
|
if (decimals === 18) {
|
||||||
|
assert.equal(parseEther(str), wei, "parseEther");
|
||||||
|
assert.equal(parseUnits(str), wei, "parseUnits");
|
||||||
|
}
|
||||||
|
assert.equal(parseUnits(str, unit), wei, `parseUnits(${ unit })`);
|
||||||
|
assert.equal(parseUnits(str, decimals), wei, `parseUnits(${ decimals })`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Tests bad unit conversion", function() {
|
||||||
|
it("fails to convert non-string value", function() {
|
||||||
|
assert.throws(() => {
|
||||||
|
parseUnits(<any>3, "ether");
|
||||||
|
}, (error: any) => {
|
||||||
|
return error.message.startsWith("value must be a string");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("fails to convert unknown unit", function() {
|
||||||
|
assert.throws(() => {
|
||||||
|
parseUnits("3", "foobar");
|
||||||
|
}, (error: any) => {
|
||||||
|
return error.message.startsWith("invalid unit");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
152
src.ts/_tests/test-utils-utf8.ts
Normal file
152
src.ts/_tests/test-utils-utf8.ts
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
import assert from "assert";
|
||||||
|
|
||||||
|
import {
|
||||||
|
toUtf8Bytes, toUtf8CodePoints, toUtf8String,
|
||||||
|
Utf8ErrorFuncs
|
||||||
|
} from "../index.js";
|
||||||
|
|
||||||
|
export type TestCaseBadString = {
|
||||||
|
name: string,
|
||||||
|
bytes: Uint8Array,
|
||||||
|
ignore: string,
|
||||||
|
replace: string,
|
||||||
|
error: string
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TestCaseCodePoints = {
|
||||||
|
name: string;
|
||||||
|
text: string;
|
||||||
|
codepoints: Array<number>;
|
||||||
|
};
|
||||||
|
|
||||||
|
describe("Tests UTF-8 bad strings", function() {
|
||||||
|
|
||||||
|
const tests: Array<TestCaseBadString> = [
|
||||||
|
{
|
||||||
|
name: "unexpected continue",
|
||||||
|
bytes: new Uint8Array([ 0x41, 0x80, 0x42, 0x43 ]),
|
||||||
|
ignore: "ABC",
|
||||||
|
replace: "A\ufffdBC",
|
||||||
|
error: "UNEXPECTED_CONTINUE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "bad prefix",
|
||||||
|
bytes: new Uint8Array([ 0x41, 0xf8, 0x42, 0x43 ]),
|
||||||
|
ignore: "ABC",
|
||||||
|
replace: "A\ufffdBC",
|
||||||
|
error: "BAD_PREFIX"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "bad prefix (multiple)",
|
||||||
|
bytes: new Uint8Array([ 0x41, 0xf8, 0x88, 0x88, 0x42, 0x43 ]),
|
||||||
|
ignore: "ABC",
|
||||||
|
replace: "A\ufffdBC",
|
||||||
|
error: "BAD_PREFIX"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "OVERRUN",
|
||||||
|
bytes: new Uint8Array([ 0x41, 0x42, 0xe2, 0x82 /* 0xac */ ]),
|
||||||
|
ignore: "AB",
|
||||||
|
replace: "AB\ufffd",
|
||||||
|
error: "OVERRUN"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "missing continue",
|
||||||
|
bytes: new Uint8Array([ 0x41, 0x42, 0xe2, 0xe2, 0x82, 0xac, 0x43 ]),
|
||||||
|
ignore: "AB\u20acC",
|
||||||
|
replace: "AB\ufffd\u20acC",
|
||||||
|
error: "MISSING_CONTINUE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "out-of-range",
|
||||||
|
bytes: new Uint8Array([ 0x41, 0x42, 0xf7, 0xbf, 0xbf, 0xbf, 0x43 ]),
|
||||||
|
ignore: "ABC",
|
||||||
|
replace: "AB\ufffdC",
|
||||||
|
error: "OUT_OF_RANGE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "UTF-16 surrogate (low)",
|
||||||
|
bytes: new Uint8Array([ 0x41, 0x42, 0xed, 0xa0, 0x80, 0x43 ]),
|
||||||
|
ignore: "ABC",
|
||||||
|
replace: "AB\ufffdC",
|
||||||
|
error: "UTF16_SURROGATE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "UTF-16 surrogate (high)",
|
||||||
|
bytes: new Uint8Array([ 0x41, 0x42, 0xed, 0xbf, 0xbf, 0x43 ]),
|
||||||
|
ignore: "ABC",
|
||||||
|
replace: "AB\ufffdC",
|
||||||
|
error: "UTF16_SURROGATE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "overlong",
|
||||||
|
bytes: new Uint8Array([ 0xf0, 0x82, 0x82, 0xac ]),
|
||||||
|
ignore: "",
|
||||||
|
replace: "\u20ac",
|
||||||
|
error: "OVERLONG"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const { name, bytes, ignore, replace, error } of tests) {
|
||||||
|
it(`correctly handles ${ name }: replace strategy`, function() {
|
||||||
|
const result = toUtf8String(bytes, Utf8ErrorFuncs.replace);
|
||||||
|
assert.equal(result, replace);
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`correctly handles ${ name }: ignore strategy`, function() {
|
||||||
|
const result = toUtf8String(bytes, Utf8ErrorFuncs.ignore);
|
||||||
|
assert.equal(result, ignore);
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`correctly handles ${ name }: error strategy`, function() {
|
||||||
|
assert.throws(() => {
|
||||||
|
const result = toUtf8String(bytes);
|
||||||
|
console.log(result);
|
||||||
|
}, (e: any) => {
|
||||||
|
return (e.message.indexOf(error) >= 0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
it("fails to get UTF-8 bytes from incomplete surrogate", function() {
|
||||||
|
assert.throws(() => {
|
||||||
|
const text = String.fromCharCode(0xd800);;
|
||||||
|
const result = toUtf8Bytes(text);
|
||||||
|
console.log(result);
|
||||||
|
}, (error: any) => {
|
||||||
|
return (error.message.startsWith("invalid surrogate pair"));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("fails to get UTF-8 bytes from invalid surrogate pair", function() {
|
||||||
|
assert.throws(() => {
|
||||||
|
const text = String.fromCharCode(0xd800, 0xdbff);;
|
||||||
|
const result = toUtf8Bytes(text);
|
||||||
|
console.log(result);
|
||||||
|
}, (error: any) => {
|
||||||
|
return (error.message.startsWith("invalid surrogate pair"));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Tests UTF-8 bad strings", function() {
|
||||||
|
|
||||||
|
const tests: Array<TestCaseCodePoints> = [
|
||||||
|
{
|
||||||
|
name: "the Euro symbol",
|
||||||
|
text: "AB\u20acC",
|
||||||
|
codepoints: [ 0x41, 0x42, 0x20ac, 0x43 ]
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const { name, text, codepoints } of tests) {
|
||||||
|
it(`expands strings to codepoints: ${ name }`, function() {
|
||||||
|
const result = toUtf8CodePoints(text);
|
||||||
|
assert.equal(result.length, codepoints.length, "codepoints.length");
|
||||||
|
for (let i = 0; i < result.length; i++) {
|
||||||
|
assert.equal(result[i], codepoints[i], `codepoints[${ i }]`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
@ -150,6 +150,24 @@ export interface TestCaseSolidityHash {
|
|||||||
/////////////////////////////
|
/////////////////////////////
|
||||||
// rlp
|
// rlp
|
||||||
|
|
||||||
|
export interface TestCaseUnit {
|
||||||
|
name: string;
|
||||||
|
wei: string;
|
||||||
|
ethers: string;
|
||||||
|
ether_format: string;
|
||||||
|
|
||||||
|
kwei?: string;
|
||||||
|
mwei?: string;
|
||||||
|
gwei?: string;
|
||||||
|
szabo?: string;
|
||||||
|
finney?: string;
|
||||||
|
finney_format?: string;
|
||||||
|
szabo_format?: string;
|
||||||
|
gwei_format?: string;
|
||||||
|
mwei_format?: string;
|
||||||
|
kwei_format?: string;
|
||||||
|
}
|
||||||
|
|
||||||
export type NestedHexString = string | Array<string | NestedHexString>;
|
export type NestedHexString = string | Array<string | NestedHexString>;
|
||||||
|
|
||||||
export interface TestCaseRlp {
|
export interface TestCaseRlp {
|
||||||
|
@ -42,6 +42,8 @@ export interface MochaRunnable {
|
|||||||
|
|
||||||
const ATTEMPTS = 5;
|
const ATTEMPTS = 5;
|
||||||
export async function retryIt(name: string, func: (this: MochaRunnable) => Promise<void>): Promise<void> {
|
export async function retryIt(name: string, func: (this: MochaRunnable) => Promise<void>): Promise<void> {
|
||||||
|
//const errors: Array<Error> = [ ];
|
||||||
|
|
||||||
it(name, async function() {
|
it(name, async function() {
|
||||||
this.timeout(ATTEMPTS * 5000);
|
this.timeout(ATTEMPTS * 5000);
|
||||||
|
|
||||||
@ -53,15 +55,20 @@ export async function retryIt(name: string, func: (this: MochaRunnable) => Promi
|
|||||||
if (error.message === "sync skip; aborting execution") {
|
if (error.message === "sync skip; aborting execution") {
|
||||||
// Skipping a test; let mocha handle it
|
// Skipping a test; let mocha handle it
|
||||||
throw error;
|
throw error;
|
||||||
|
|
||||||
} else if (error.code === "ERR_ASSERTION") {
|
} else if (error.code === "ERR_ASSERTION") {
|
||||||
// Assertion error; let mocha scold us
|
// Assertion error; let mocha scold us
|
||||||
throw error;
|
throw error;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
//errors.push(error);
|
||||||
|
|
||||||
if (i === ATTEMPTS - 1) {
|
if (i === ATTEMPTS - 1) {
|
||||||
stats.pushRetry(i, name, error);
|
throw error;
|
||||||
|
//stats.pushRetry(i, name, error);
|
||||||
} else {
|
} else {
|
||||||
await stall(500 * (1 << i));
|
await stall(500 * (1 << i));
|
||||||
stats.pushRetry(i, name, null);
|
//stats.pushRetry(i, name, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -72,6 +79,7 @@ export async function retryIt(name: string, func: (this: MochaRunnable) => Promi
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
export interface StatSet {
|
export interface StatSet {
|
||||||
name: string;
|
name: string;
|
||||||
retries: Array<{ message: string, error: null | Error }>;
|
retries: Array<{ message: string, error: null | Error }>;
|
||||||
@ -80,11 +88,11 @@ export interface StatSet {
|
|||||||
const _guard = { };
|
const _guard = { };
|
||||||
|
|
||||||
export class Stats {
|
export class Stats {
|
||||||
#stats: Array<StatSet>;
|
// #stats: Array<StatSet>;
|
||||||
|
|
||||||
constructor(guard: any) {
|
constructor(guard: any) {
|
||||||
if (guard !== _guard) { throw new Error("private constructor"); }
|
if (guard !== _guard) { throw new Error("private constructor"); }
|
||||||
this.#stats = [ ];
|
// this.#stats = [ ];
|
||||||
}
|
}
|
||||||
|
|
||||||
#currentStats(): StatSet {
|
#currentStats(): StatSet {
|
||||||
@ -124,3 +132,4 @@ export class Stats {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const stats = new Stats(_guard);
|
export const stats = new Stats(_guard);
|
||||||
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user