From 70c1f64854ba9ebcac5825f1186de619e21f7d4b Mon Sep 17 00:00:00 2001 From: William Chargin Date: Thu, 7 Jun 2018 09:32:06 -0700 Subject: [PATCH] Use new unified addresses in Graph V3 (#361) Summary: This is basically a textual substitution. Test Plan: Existing unit tests suffice. Note that `_address.js` (with underscore) is no longer imported except from its own tests. wchargin-branch: unified-addresses-in-graph --- src/v3/core/graph.js | 77 +++++++++++++++------------------ src/v3/core/graph.test.js | 91 ++++++++++++++------------------------- 2 files changed, 66 insertions(+), 102 deletions(-) diff --git a/src/v3/core/graph.js b/src/v3/core/graph.js index 075dd98..19be943 100644 --- a/src/v3/core/graph.js +++ b/src/v3/core/graph.js @@ -1,36 +1,27 @@ // @flow -import type {NodeAddress, EdgeAddress} from "./_address"; -import * as Address from "./_address"; import {makeAddressModule, type AddressModule} from "./address"; -export type {NodeAddress, EdgeAddress} from "./_address"; - -// New-style node and edge address types and modules. Will be made -// public once implementation is complete. -export opaque type _NodeAddressT: string = string; -export opaque type _EdgeAddressT: string = string; -export const _NodeAddress: AddressModule<_NodeAddressT> = (makeAddressModule({ +export opaque type NodeAddressT: string = string; +export opaque type EdgeAddressT: string = string; +export const NodeAddress: AddressModule = (makeAddressModule({ name: "NodeAddress", nonce: "N", otherNonces: new Map().set("E", "EdgeAddress"), }): AddressModule); -export const _EdgeAddress: AddressModule<_EdgeAddressT> = (makeAddressModule({ +export const EdgeAddress: AddressModule = (makeAddressModule({ name: "EdgeAddress", nonce: "E", otherNonces: new Map().set("N", "NodeAddress"), }): AddressModule); -Object.freeze(Address); -export {Address}; - export type Edge = {| - +address: EdgeAddress, - +src: NodeAddress, - +dst: NodeAddress, + +address: EdgeAddressT, + +src: NodeAddressT, + +dst: NodeAddressT, |}; -export type Neighbor = {|+node: NodeAddress, +edge: Edge|}; +export type Neighbor = {|+node: NodeAddressT, +edge: Edge|}; export opaque type DirectionT = Symbol; export const Direction: {| @@ -45,8 +36,8 @@ export const Direction: {| export type NeighborsOptions = {| +direction: DirectionT, - +nodePrefix: NodeAddress, - +edgePrefix: EdgeAddress, + +nodePrefix: NodeAddressT, + +edgePrefix: EdgeAddressT, |}; export opaque type GraphJSON = any; // TODO @@ -59,10 +50,10 @@ export class Graph { // // Invariant: If an edge `e` is in the graph, then `e.src` and `e.dst` // are both in the graph. - _nodes: Set; - _edges: Map; - _inEdges: Map; - _outEdges: Map; + _nodes: Set; + _edges: Map; + _inEdges: Map; + _outEdges: Map; constructor(): void { this._nodes = new Set(); @@ -71,14 +62,14 @@ export class Graph { this._outEdges = new Map(); } - addNode(a: NodeAddress): this { - Address.assertNodeAddress(a); + addNode(a: NodeAddressT): this { + NodeAddress.assertValid(a); this._nodes.add(a); return this; } - removeNode(a: NodeAddress): this { - Address.assertNodeAddress(a); + removeNode(a: NodeAddressT): this { + NodeAddress.assertValid(a); for (const e of this.edges()) { if (e.src === a || e.dst === a) { const srcOrDst = e.src === a ? "src" : "dst"; @@ -91,19 +82,19 @@ export class Graph { return this; } - hasNode(a: NodeAddress): boolean { - Address.assertNodeAddress(a); + hasNode(a: NodeAddressT): boolean { + NodeAddress.assertValid(a); return this._nodes.has(a); } - *nodes(): Iterator { + *nodes(): Iterator { yield* this._nodes; } addEdge(edge: Edge): this { - Address.assertNodeAddress(edge.src, "edge.src"); - Address.assertNodeAddress(edge.dst, "edge.dst"); - Address.assertEdgeAddress(edge.address, "edge.address"); + NodeAddress.assertValid(edge.src, "edge.src"); + NodeAddress.assertValid(edge.dst, "edge.dst"); + EdgeAddress.assertValid(edge.address, "edge.address"); const srcMissing = !this._nodes.has(edge.src); const dstMissing = !this._nodes.has(edge.dst); @@ -129,19 +120,19 @@ export class Graph { return this; } - removeEdge(address: EdgeAddress): this { - Address.assertEdgeAddress(address); + removeEdge(address: EdgeAddressT): this { + EdgeAddress.assertValid(address); this._edges.delete(address); return this; } - hasEdge(address: EdgeAddress): boolean { - Address.assertEdgeAddress(address); + hasEdge(address: EdgeAddressT): boolean { + EdgeAddress.assertValid(address); return this._edges.has(address); } - edge(address: EdgeAddress): ?Edge { - Address.assertEdgeAddress(address); + edge(address: EdgeAddressT): ?Edge { + EdgeAddress.assertValid(address); return this._edges.get(address); } @@ -149,7 +140,7 @@ export class Graph { yield* this._edges.values(); } - neighbors(node: NodeAddress, options: NeighborsOptions): Iterator { + neighbors(node: NodeAddressT, options: NeighborsOptions): Iterator { const _ = {node, options}; throw new Error("neighbors"); } @@ -174,8 +165,8 @@ export class Graph { } export function edgeToString(edge: Edge): string { - const address = Address.edgeToString(edge.address); - const src = Address.nodeToString(edge.src); - const dst = Address.nodeToString(edge.dst); + const address = EdgeAddress.toString(edge.address); + const src = NodeAddress.toString(edge.src); + const dst = NodeAddress.toString(edge.dst); return `{address: ${address}, src: ${src}, dst: ${dst}}`; } diff --git a/src/v3/core/graph.test.js b/src/v3/core/graph.test.js index 49cb969..97742a5 100644 --- a/src/v3/core/graph.test.js +++ b/src/v3/core/graph.test.js @@ -1,48 +1,21 @@ // @flow import { - type EdgeAddress, - type NodeAddress, - type _EdgeAddressT, - type _NodeAddressT, - Address, + type EdgeAddressT, + type NodeAddressT, Direction, + EdgeAddress, Graph, + NodeAddress, edgeToString, } from "./graph"; describe("core/graph", () => { - const {nodeAddress, edgeAddress} = Address; - describe("Address re-exports", () => { - it("exist", () => { - expect(Address).toEqual(expect.anything()); - }); - it("include distinct NodeAddress and EdgeAddress types", () => { - const node: NodeAddress = nodeAddress([]); - const edge: EdgeAddress = edgeAddress([]); - // $ExpectFlowError - const _unused_badNodeAddress: NodeAddress = edge; - // $ExpectFlowError - const _unused_badEdgeAddress: EdgeAddress = node; - }); - it("are read-only", () => { - const originalToParts = Address.toParts; - const wonkyToParts: typeof originalToParts = (a) => [ - ...originalToParts(a), - "wat", - ]; - expect(() => { - // $ExpectFlowError - Address.toParts = wonkyToParts; - }).toThrow(/read.only property/); - }); - }); - function _unused_itExportsDistinctNodeAddressAndEdgeAddressTypes() { // $ExpectFlowError - const _unused_nodeToEdge = (x: _NodeAddressT): _EdgeAddressT => x; + const _unused_nodeToEdge = (x: NodeAddressT): EdgeAddressT => x; // $ExpectFlowError - const _unused_edgeToNode = (x: _EdgeAddressT): _NodeAddressT => x; + const _unused_edgeToNode = (x: EdgeAddressT): NodeAddressT => x; } describe("Direction values", () => { @@ -80,7 +53,7 @@ describe("core/graph", () => { describe("edge addresses", () => { function rejectsEdgeAddress(f) { it(`${f.name} rejects EdgeAddress`, () => { - const e = edgeAddress(["foo"]); + const e = EdgeAddress.fromParts(["foo"]); // $ExpectFlowError expect(() => f.call(new Graph(), e)).toThrow("got EdgeAddress"); }); @@ -88,9 +61,9 @@ describe("core/graph", () => { nodeMethods.forEach(rejectsEdgeAddress); }); describe("remove a node that is some edge's", () => { - const src = nodeAddress(["src"]); - const dst = nodeAddress(["dst"]); - const address = edgeAddress(["edge"]); + const src = NodeAddress.fromParts(["src"]); + const dst = NodeAddress.fromParts(["dst"]); + const address = EdgeAddress.fromParts(["edge"]); const edge = () => ({src, dst, address}); const graph = () => new Graph() @@ -111,7 +84,7 @@ describe("core/graph", () => { }); describe("work on", () => { - const n1 = nodeAddress(["foo"]); + const n1 = NodeAddress.fromParts(["foo"]); it("a graph with no nodes", () => { const graph = new Graph(); expect(graph.hasNode(n1)).toBe(false); @@ -146,7 +119,7 @@ describe("core/graph", () => { expect(Array.from(graph.nodes())).toHaveLength(0); }); it("a graph with two nodes", () => { - const n2 = nodeAddress([""]); + const n2 = NodeAddress.fromParts([""]); const graph = new Graph().addNode(n1).addNode(n2); expect(graph.hasNode(n1)).toBe(true); expect(graph.hasNode(n2)).toBe(true); @@ -167,7 +140,7 @@ describe("core/graph", () => { describe("node addresses", () => { function rejectsNodeAddress(f) { it(`${f.name} rejects NodeAddress`, () => { - const e = nodeAddress(["foo"]); + const e = NodeAddress.fromParts(["foo"]); // $ExpectFlowError expect(() => f.call(new Graph(), e)).toThrow("got NodeAddress"); }); @@ -177,9 +150,9 @@ describe("core/graph", () => { describe("addEdge edge validation", () => { describe("throws on absent", () => { - const src = nodeAddress(["src"]); - const dst = nodeAddress(["dst"]); - const address = edgeAddress(["hi"]); + const src = NodeAddress.fromParts(["src"]); + const dst = NodeAddress.fromParts(["dst"]); + const address = EdgeAddress.fromParts(["hi"]); it("src", () => { expect(() => new Graph().addNode(dst).addEdge({src, dst, address}) @@ -193,8 +166,8 @@ describe("core/graph", () => { }); describe("throws on edge with", () => { - const n = nodeAddress(["foo"]); - const e = edgeAddress(["bar"]); + const n = NodeAddress.fromParts(["foo"]); + const e = EdgeAddress.fromParts(["bar"]); const x = "foomlio"; const badEdges = [ { @@ -240,9 +213,9 @@ describe("core/graph", () => { }); describe("on a graph", () => { - const src = nodeAddress(["foo"]); - const dst = nodeAddress(["bar"]); - const address = edgeAddress(["yay"]); + const src = NodeAddress.fromParts(["foo"]); + const dst = NodeAddress.fromParts(["bar"]); + const address = EdgeAddress.fromParts(["yay"]); describe("that has no edges or nodes", () => { it("`hasEdge` is false for some address", () => { @@ -298,8 +271,8 @@ describe("core/graph", () => { }); describe("with multiple loop edges", () => { - const e1 = edgeAddress(["e1"]); - const e2 = edgeAddress(["e2"]); + const e1 = EdgeAddress.fromParts(["e1"]); + const e2 = EdgeAddress.fromParts(["e2"]); const edge1 = {src, dst: src, address: e1}; const edge2 = {src, dst: src, address: e2}; const quiver = () => @@ -325,9 +298,9 @@ describe("core/graph", () => { }); describe("idempotency of", () => { - const src = nodeAddress(["src"]); - const dst = nodeAddress(["dst"]); - const address = edgeAddress(["hi"]); + const src = NodeAddress.fromParts(["src"]); + const dst = NodeAddress.fromParts(["dst"]); + const address = EdgeAddress.fromParts(["hi"]); it("`addEdge`", () => { const g = new Graph() .addNode(src) @@ -352,15 +325,15 @@ describe("core/graph", () => { describe("edgeToString", () => { it("works", () => { const edge = { - address: Address.edgeAddress(["one", "two"]), - dst: Address.nodeAddress(["five", "six"]), - src: Address.nodeAddress(["three", "four"]), + address: EdgeAddress.fromParts(["one", "two"]), + dst: NodeAddress.fromParts(["five", "six"]), + src: NodeAddress.fromParts(["three", "four"]), }; const expected = "{" + - 'address: edgeAddress(["one","two"]), ' + - 'src: nodeAddress(["three","four"]), ' + - 'dst: nodeAddress(["five","six"])' + + 'address: EdgeAddress["one","two"], ' + + 'src: NodeAddress["three","four"], ' + + 'dst: NodeAddress["five","six"]' + "}"; expect(edgeToString(edge)).toEqual(expected); });