Add StateTransitionMachine.loadGraphAndRunPagerank (#758)

* StateTransitionMachine.loadGraph reports success

Step one towards #586. This will enable us to chain runPagerank after
loadGraph only if the load went through successfully.

Test plan: Unit tests included.

* Add StateTransitionMachine.loadGraphAndRunPagerank

This methods combines `loadGraph` and `runPagerank` into one method
which internally chains the two method. `runPagerank` is only called if
`loadGraph` was successful.

Progress on #586.

Test plan:
The new method has attached unit tests. I implemented the unit tests via
mocking, which seemed quite convenient as the method is basically a
wrapper for chaining two other function calls.
This commit is contained in:
Dandelion Mané 2018-09-03 14:33:52 -07:00 committed by GitHub
parent 241905f6d8
commit 1135141054
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 82 additions and 0 deletions

View File

@ -24,6 +24,7 @@ describe("app/credExplorer/App", () => {
const setEdgeEvaluator = jest.fn();
const loadGraph = jest.fn();
const runPagerank = jest.fn();
const loadGraphAndRunPagerank = jest.fn();
const localStore = testLocalStore();
function createMockSTM(_getState, _setState) {
setState = _setState;
@ -33,6 +34,7 @@ describe("app/credExplorer/App", () => {
setEdgeEvaluator,
loadGraph,
runPagerank,
loadGraphAndRunPagerank,
};
}
const App = createApp(createMockSTM);

View File

@ -81,6 +81,7 @@ export interface StateTransitionMachineInterface {
+setEdgeEvaluator: (EdgeEvaluator) => void;
+loadGraph: (Assets) => Promise<boolean>;
+runPagerank: (NodeAddressT) => Promise<void>;
+loadGraphAndRunPagerank: (Assets, NodeAddressT) => Promise<void>;
}
/* In production, instantiate via createStateTransitionMachine; the constructor
* implementation allows specification of the loadGraphWithAdapters and
@ -256,6 +257,32 @@ export class StateTransitionMachine implements StateTransitionMachineInterface {
this.setState(NullUtil.get(newState));
}
}
async loadGraphAndRunPagerank(
assets: Assets,
totalScoreNodePrefix: NodeAddressT
) {
const state = this.getState();
if (state.type === "UNINITIALIZED") {
throw new Error("Tried to load and run from incorrect state");
}
switch (state.substate.type) {
case "READY_TO_LOAD_GRAPH":
const loadedGraph = await this.loadGraph(assets);
if (loadedGraph) {
await this.runPagerank(totalScoreNodePrefix);
}
break;
case "READY_TO_RUN_PAGERANK":
await this.runPagerank(totalScoreNodePrefix);
break;
case "PAGERANK_EVALUATED":
await this.runPagerank(totalScoreNodePrefix);
break;
default:
throw new Error((state.substate.type: empty));
}
}
}
export type GraphWithAdapters = {|

View File

@ -343,4 +343,57 @@ describe("app/credExplorer/state", () => {
expect(console.error).toHaveBeenCalledWith(error);
});
});
describe("loadGraphAndRunPagerank", () => {
it("errors if called with uninitialized state", async () => {
const {stm} = example(initialState());
await expect(
stm.loadGraphAndRunPagerank(new Assets("gateway"), NodeAddress.empty)
).rejects.toThrow("incorrect state");
});
it("when READY_TO_LOAD_GRAPH, loads graph then runs pagerank", async () => {
const {stm} = example(readyToLoadGraph());
(stm: any).loadGraph = jest.fn();
(stm: any).runPagerank = jest.fn();
stm.loadGraph.mockResolvedValue(true);
const assets = new Assets("/gateway/");
const prefix = NodeAddress.fromParts(["bar"]);
await stm.loadGraphAndRunPagerank(assets, prefix);
expect(stm.loadGraph).toHaveBeenCalledTimes(1);
expect(stm.loadGraph).toHaveBeenCalledWith(assets);
expect(stm.runPagerank).toHaveBeenCalledTimes(1);
expect(stm.runPagerank).toHaveBeenCalledWith(prefix);
});
it("does not run pagerank if loadGraph did not succeed", async () => {
const {stm} = example(readyToLoadGraph());
(stm: any).loadGraph = jest.fn();
(stm: any).runPagerank = jest.fn();
stm.loadGraph.mockResolvedValue(false);
const assets = new Assets("/gateway/");
const prefix = NodeAddress.fromParts(["bar"]);
await stm.loadGraphAndRunPagerank(assets, prefix);
expect(stm.loadGraph).toHaveBeenCalledTimes(1);
expect(stm.runPagerank).toHaveBeenCalledTimes(0);
});
it("when READY_TO_RUN_PAGERANK, runs pagerank", async () => {
const {stm} = example(readyToRunPagerank());
(stm: any).loadGraph = jest.fn();
(stm: any).runPagerank = jest.fn();
const prefix = NodeAddress.fromParts(["bar"]);
await stm.loadGraphAndRunPagerank(new Assets("/gateway/"), prefix);
expect(stm.loadGraph).toHaveBeenCalledTimes(0);
expect(stm.runPagerank).toHaveBeenCalledTimes(1);
expect(stm.runPagerank).toHaveBeenCalledWith(prefix);
});
it("when PAGERANK_EVALUATED, runs pagerank", async () => {
const {stm} = example(pagerankEvaluated());
(stm: any).loadGraph = jest.fn();
(stm: any).runPagerank = jest.fn();
const prefix = NodeAddress.fromParts(["bar"]);
await stm.loadGraphAndRunPagerank(new Assets("/gateway/"), prefix);
expect(stm.loadGraph).toHaveBeenCalledTimes(0);
expect(stm.runPagerank).toHaveBeenCalledTimes(1);
expect(stm.runPagerank).toHaveBeenCalledWith(prefix);
});
});
});