Backend: add ComputeFunction (#1620)

Similar to PluginLoaders, this accepts an interface like
TimelineCred.compute. During a load, we have the added
responsiblity of using the TaskReporter.

This lets us mock the concrete TimelineCred.compute, while testing
just the extra functionality. The responsiblity to compose this
with the concrete TimelineCred.compute lies with LoadContext.
This commit is contained in:
Robin van Boven 2020-02-04 12:45:48 +01:00 committed by GitHub
parent 492f2ff6b4
commit 806919a6cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 105 additions and 0 deletions

View File

@ -0,0 +1,35 @@
//@flow
import {type WeightedGraph} from "../core/weightedGraph";
import {TaskReporter} from "../util/taskReporter";
import {type TimelineCredParameters} from "../analysis/timeline/params";
import {type PluginDeclaration} from "../analysis/pluginDeclaration";
import {TimelineCred} from "../analysis/timeline/timelineCred";
/**
* An abstract handle for TimelineCred.compute-like functions.
*/
export type ComputeFunction = (opts: ComputeOpts) => Promise<TimelineCred>;
// Note: type should allow extra properties, it's expected to be a subset.
type ComputeEnv = {
+reporter: TaskReporter,
};
type ComputeOpts = {|
weightedGraph: WeightedGraph,
params?: $Shape<TimelineCredParameters>,
// TODO(@decentralion, #1557): remove plugins arg
plugins: $ReadOnlyArray<PluginDeclaration>,
|};
export async function computeTask(
compute: ComputeFunction,
{reporter}: ComputeEnv,
opts: ComputeOpts
): Promise<TimelineCred> {
reporter.start("compute-cred");
const cred = await compute(opts);
reporter.finish("compute-cred");
return cred;
}

View File

@ -0,0 +1,70 @@
// @flow
import {TestTaskReporter} from "../util/taskReporter";
import {TimelineCred} from "../analysis/timeline/timelineCred";
import {type ComputeFunction, computeTask} from "./computeFunction";
const mockCompute = () => jest.fn();
const fakeWeightedGraph = ({is: "fake-weighted-graph"}: any);
const fakeCred = ({
toJSON: () => ({is: "fake-cred"}),
}: any);
describe("src/backend/computeFunction", () => {
describe("ComputeFunction", () => {
it("should match the TimelineCred.compute signature", () => {
const _: ComputeFunction = TimelineCred.compute;
});
});
describe("computeTask", () => {
it("should defer to the provided compute function", async () => {
// Given
const plugins = [];
const reporter = new TestTaskReporter();
const params = {alpha: 0.456};
const compute = mockCompute();
compute.mockResolvedValueOnce(fakeCred);
// When
const cred = await computeTask(
compute,
{reporter},
{weightedGraph: fakeWeightedGraph, plugins, params}
);
// Then
expect(cred).toEqual(fakeCred);
expect(compute).toBeCalledTimes(1);
expect(compute).toBeCalledWith({
weightedGraph: fakeWeightedGraph,
plugins,
params,
});
});
it("should give the right tasks to the TaskReporter", async () => {
// Given
const plugins = [];
const reporter = new TestTaskReporter();
const params = {alpha: 0.456};
const compute = mockCompute();
compute.mockResolvedValueOnce(fakeCred);
// When
await computeTask(
compute,
{reporter},
{weightedGraph: fakeWeightedGraph, plugins, params}
);
// Then
expect(reporter.activeTasks()).toEqual([]);
expect(reporter.entries()).toEqual([
{type: "START", taskId: "compute-cred"},
{type: "FINISH", taskId: "compute-cred"},
]);
});
});
});