Include context parameters for address assertions (#346)

Summary:
Now, a client calling `assertNodeAddress` can indicate the context to
clients, like `assertNodeAddress(foo.bar.node, "foo.bar.node")`.

Paired with @decentralion.

Test Plan:
Unit tests updated. Existing graph code does not need to be updated,
because the default values work fine.

wchargin-branch: assertion-context-parameters
This commit is contained in:
William Chargin 2018-06-05 11:53:39 -07:00 committed by GitHub
parent 24c3b2ec41
commit 4705bec20d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 30 additions and 17 deletions

View File

@ -30,58 +30,65 @@ function addressType(x: string): ?AddressType {
} }
} }
export function assertNodeAddress(x: NodeAddress) { export function assertNodeAddress(x: NodeAddress, what: string = "node") {
const type = addressType(x); const type = addressType(x);
switch (type) { switch (type) {
case "NODE": case "NODE":
return; return;
case "EDGE": case "EDGE":
throw new Error(`Expected NodeAddress, got EdgeAddress: ${stringify(x)}`); throw new Error(
`${what}: expected NodeAddress, got EdgeAddress: ${stringify(x)}`
);
case null: case null:
case undefined: case undefined:
throw new Error(`Bad address: ${stringify(x)}`); throw new Error(`${what}: bad address: ${stringify(x)}`);
default: default:
// eslint-disable-next-line no-unused-expressions // eslint-disable-next-line no-unused-expressions
(type: empty); (type: empty);
throw new Error(`Invariant violation: ${stringify(x)}`); throw new Error(`${what}: invariant violation: ${stringify(x)}`);
} }
} }
export function assertEdgeAddress(x: EdgeAddress) { export function assertEdgeAddress(x: EdgeAddress, what: string = "edge") {
const type = addressType(x); const type = addressType(x);
switch (type) { switch (type) {
case "NODE": case "NODE":
throw new Error(`Expected EdgeAddress, got NodeAddress: ${stringify(x)}`); throw new Error(
`${what}: expected EdgeAddress, got NodeAddress: ${stringify(x)}`
);
case "EDGE": case "EDGE":
return; return;
case null: case null:
case undefined: case undefined:
throw new Error(`Bad address: ${stringify(x)}`); throw new Error(`${what}: bad address: ${stringify(x)}`);
default: default:
// eslint-disable-next-line no-unused-expressions // eslint-disable-next-line no-unused-expressions
(type: empty); (type: empty);
throw new Error(`Invariant violation: ${stringify(x)}`); throw new Error(`${what}: invariant violation: ${stringify(x)}`);
} }
} }
export function assertAddress(x: GenericAddress) { export function assertAddress(x: GenericAddress, what: string = "address") {
if (addressType(x) == null) { if (addressType(x) == null) {
throw new Error( throw new Error(
`Expected NodeAddress or EdgeAddress, got: ${stringify(x)}` `${what}: expected NodeAddress or EdgeAddress, got: ${stringify(x)}`
); );
} }
} }
export function assertAddressArray(arr: $ReadOnlyArray<string>) { export function assertAddressArray(
arr: $ReadOnlyArray<string>,
what: string = "address array"
) {
if (arr == null) { if (arr == null) {
throw new Error(String(arr)); throw new Error(String(arr));
} }
arr.forEach((s: string) => { arr.forEach((s: string) => {
if (s == null) { if (s == null) {
throw new Error(`${String(s)} in ${stringify(arr)}`); throw new Error(`${what}: ${String(s)} in ${stringify(arr)}`);
} }
if (s.indexOf(SEPARATOR) !== -1) { if (s.indexOf(SEPARATOR) !== -1) {
throw new Error(`NUL char: ${stringify(arr)}`); throw new Error(`${what}: NUL char: ${stringify(arr)}`);
} }
}); });
} }

View File

@ -53,7 +53,7 @@ describe("core/address", () => {
throwOnNullOrUndefined(toParts); throwOnNullOrUndefined(toParts);
it("throws on malformed address", () => { it("throws on malformed address", () => {
// $ExpectFlowError // $ExpectFlowError
expect(() => toParts("zookomoobo")).toThrow(/Expected .*Address/); expect(() => toParts("zookomoobo")).toThrow(/expected .*Address/);
}); });
it("throws on fake (slash-separated) node address", () => { it("throws on fake (slash-separated) node address", () => {
// $ExpectFlowError // $ExpectFlowError
@ -104,12 +104,12 @@ describe("core/address", () => {
}); });
it("malformed base", () => { it("malformed base", () => {
// $ExpectFlowError // $ExpectFlowError
expect(() => f("foo", "foo")).toThrow("Bad address"); expect(() => f("foo", "foo")).toThrow("bad address");
}); });
it("base of wrong kind", () => { it("base of wrong kind", () => {
// $ExpectFlowError // $ExpectFlowError
expect(() => f(badConstructor(["foo"]), "foo")).toThrow( expect(() => f(badConstructor(["foo"]), "foo")).toThrow(
/Expected.*Address/ /expected.*Address/
); );
}); });
it("invalid component", () => { it("invalid component", () => {
@ -159,8 +159,14 @@ describe("core/address", () => {
expect(() => f(bad)).toThrow(badMsg); expect(() => f(bad)).toThrow(badMsg);
}); });
it("errors on non-address", () => { it("errors on non-address", () => {
it("errors on the wrong type of address with a custom message", () => {
// $ExpectFlowError
expect(() => f(bad, "widget")).toThrow(
new RegExp("widget:.*" + badMsg)
);
});
// $ExpectFlowError // $ExpectFlowError
expect(() => f("foomulous")).toThrow("Bad address:"); expect(() => f("foomulous")).toThrow("bad address:");
}); });
}); });
} }