Add top-level address module error handling (#356)
Summary: This commit implements all the code needed for the top-level `makeAddressModule` function, without implementing any of the address functions. This mostly comprises handling of errors in the module options. Test Plan: Unit tests added. Run `yarn travis`. wchargin-branch: address-error-handling
This commit is contained in:
parent
fc7e8886b1
commit
c1a5e01a2c
|
@ -1,5 +1,7 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
|
import stringify from "json-stable-stringify";
|
||||||
|
|
||||||
export interface AddressModule<Address> {
|
export interface AddressModule<Address> {
|
||||||
/**
|
/**
|
||||||
* Assert at runtime that the provided address is actually a valid
|
* Assert at runtime that the provided address is actually a valid
|
||||||
|
@ -89,7 +91,31 @@ export type Options = {|
|
||||||
|
|
||||||
export function makeAddressModule(options: Options): AddressModule<string> {
|
export function makeAddressModule(options: Options): AddressModule<string> {
|
||||||
type Address = string; // for readability and interface consistency
|
type Address = string; // for readability and interface consistency
|
||||||
const _ = options;
|
const {name, nonce} = options;
|
||||||
|
const otherNonces = new Map(options.otherNonces || new Map());
|
||||||
|
|
||||||
|
const separator = "\0";
|
||||||
|
if (nonce.indexOf(separator) !== -1) {
|
||||||
|
throw new Error(`invalid nonce (contains NUL): ${stringify(nonce)}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const nonceWithSeparator = nonce + separator;
|
||||||
|
const otherNoncesWithSeparators = new Map();
|
||||||
|
for (const [otherNonce, otherName] of otherNonces.entries()) {
|
||||||
|
if (otherNonce === nonce) {
|
||||||
|
throw new Error(
|
||||||
|
`primary nonce listed as otherNonce: ${stringify(nonce)}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (otherNonce.indexOf(separator) !== -1) {
|
||||||
|
throw new Error(
|
||||||
|
`invalid otherNonce (contains NUL): ${stringify(otherNonce)}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
otherNoncesWithSeparators.set(otherNonce + separator, otherName);
|
||||||
|
}
|
||||||
|
|
||||||
|
const _ = {name, nonceWithSeparator};
|
||||||
|
|
||||||
function assertValid(address: Address, what?: string): void {
|
function assertValid(address: Address, what?: string): void {
|
||||||
const _ = {address, what};
|
const _ = {address, what};
|
||||||
|
|
|
@ -28,6 +28,29 @@ describe("core/address", () => {
|
||||||
it("makes address modules using all the options", () => {
|
it("makes address modules using all the options", () => {
|
||||||
makeModules();
|
makeModules();
|
||||||
});
|
});
|
||||||
|
it("rejects a module whose nonce contains NUL", () => {
|
||||||
|
expect(() => {
|
||||||
|
makeAddressModule({name: "BadAddress", nonce: "n\0o"});
|
||||||
|
}).toThrow("invalid nonce (contains NUL):");
|
||||||
|
});
|
||||||
|
it("rejects a module with `otherNonces` containing NUL", () => {
|
||||||
|
expect(() => {
|
||||||
|
makeAddressModule({
|
||||||
|
name: "GoodAddress",
|
||||||
|
nonce: "G",
|
||||||
|
otherNonces: new Map().set("n\0o", "BadAddress"),
|
||||||
|
});
|
||||||
|
}).toThrow("invalid otherNonce (contains NUL):");
|
||||||
|
});
|
||||||
|
it("rejects a module with `nonce` in `otherNonces`", () => {
|
||||||
|
expect(() => {
|
||||||
|
makeAddressModule({
|
||||||
|
name: "GoodAddress",
|
||||||
|
nonce: "G",
|
||||||
|
otherNonces: new Map().set("G", "WatAddress"),
|
||||||
|
});
|
||||||
|
}).toThrow("primary nonce listed as otherNonce");
|
||||||
|
});
|
||||||
it("returns an object with read-only properties", () => {
|
it("returns an object with read-only properties", () => {
|
||||||
const {FooAddress} = makeModules();
|
const {FooAddress} = makeModules();
|
||||||
expect(() => {
|
expect(() => {
|
||||||
|
|
Loading…
Reference in New Issue