refactor(WebWorker): Abstract message passing and serialization to UIMessageBroker
closes #3703 Closes #3815
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
library angular2.test.web_workers.worker.mock_event_emitter;
|
||||
|
||||
import 'dart:core';
|
||||
import 'dart:async';
|
||||
import "package:angular2/src/facade/async.dart";
|
||||
|
||||
class MockEventEmitter extends EventEmitter {
|
||||
List<Function> _nextFns = new List();
|
||||
|
||||
@override
|
||||
StreamSubscription listen(void onData(dynamic line),
|
||||
{void onError(Error error), void onDone(), bool cancelOnError}) {
|
||||
_nextFns.add(onData);
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
void add(value) {
|
||||
_nextFns.forEach((fn) => fn(value));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import {EventEmitter} from 'angular2/src/facade/async';
|
||||
import * as Rx from 'rx';
|
||||
import {ListWrapper} from 'angular2/src/facade/collection';
|
||||
|
||||
export class MockEventEmitter extends EventEmitter {
|
||||
private _nextFns: List<Function> = [];
|
||||
|
||||
constructor() { super(); }
|
||||
|
||||
observer(generator: any): Rx.IDisposable {
|
||||
this._nextFns.push(generator.next);
|
||||
return null;
|
||||
}
|
||||
|
||||
next(value: any) {
|
||||
ListWrapper.forEach(this._nextFns, (fn) => { fn(value); });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
import {
|
||||
AsyncTestCompleter,
|
||||
inject,
|
||||
describe,
|
||||
it,
|
||||
expect,
|
||||
beforeEach,
|
||||
createTestInjector,
|
||||
beforeEachBindings,
|
||||
SpyObject,
|
||||
proxy
|
||||
} from 'angular2/test_lib';
|
||||
import {createPairedMessageBuses} from '../shared/web_worker_test_util';
|
||||
import {Serializer, PRIMITIVE} from 'angular2/src/web_workers/shared/serializer';
|
||||
import {ServiceMessageBroker} from 'angular2/src/web_workers/shared/service_message_broker';
|
||||
import {ObservableWrapper, PromiseWrapper} from 'angular2/src/facade/async';
|
||||
import {bind} from 'angular2/di';
|
||||
import {ON_WEB_WORKER} from 'angular2/src/web_workers/shared/api';
|
||||
import {RenderProtoViewRefStore} from 'angular2/src/web_workers/shared/render_proto_view_ref_store';
|
||||
import {
|
||||
RenderViewWithFragmentsStore
|
||||
} from 'angular2/src/web_workers/shared/render_view_with_fragments_store';
|
||||
|
||||
export function main() {
|
||||
const CHANNEL = "UIMessageBroker Test Channel";
|
||||
const TEST_METHOD = "TEST_METHOD";
|
||||
const PASSED_ARG_1 = 5;
|
||||
const PASSED_ARG_2 = 'TEST';
|
||||
const RESULT = 20;
|
||||
const ID = "methodId";
|
||||
|
||||
beforeEachBindings(() => [
|
||||
bind(ON_WEB_WORKER)
|
||||
.toValue(true),
|
||||
RenderProtoViewRefStore,
|
||||
RenderViewWithFragmentsStore
|
||||
]);
|
||||
|
||||
describe("UIMessageBroker", () => {
|
||||
var messageBuses;
|
||||
|
||||
beforeEach(() => { messageBuses = createPairedMessageBuses(); });
|
||||
it("should call registered method with correct arguments",
|
||||
inject([Serializer], (serializer) => {
|
||||
var broker = new ServiceMessageBroker(messageBuses.ui, serializer, CHANNEL);
|
||||
broker.registerMethod(TEST_METHOD, [PRIMITIVE, PRIMITIVE], (arg1, arg2) => {
|
||||
expect(arg1).toEqual(PASSED_ARG_1);
|
||||
expect(arg2).toEqual(PASSED_ARG_2);
|
||||
});
|
||||
ObservableWrapper.callNext(messageBuses.worker.to(CHANNEL),
|
||||
{'method': TEST_METHOD, 'args': [PASSED_ARG_1, PASSED_ARG_2]});
|
||||
}));
|
||||
|
||||
it("should return promises to the worker", inject([Serializer], (serializer) => {
|
||||
var broker = new ServiceMessageBroker(messageBuses.ui, serializer, CHANNEL);
|
||||
broker.registerMethod(TEST_METHOD, [PRIMITIVE], (arg1) => {
|
||||
expect(arg1).toEqual(PASSED_ARG_1);
|
||||
return PromiseWrapper.wrap(() => { return RESULT; });
|
||||
});
|
||||
ObservableWrapper.callNext(messageBuses.worker.to(CHANNEL),
|
||||
{'method': TEST_METHOD, 'id': ID, 'args': [PASSED_ARG_1]});
|
||||
ObservableWrapper.subscribe(messageBuses.worker.from(CHANNEL), (data: any) => {
|
||||
expect(data.type).toEqual("result");
|
||||
expect(data.id).toEqual(ID);
|
||||
expect(data.value).toEqual(RESULT);
|
||||
});
|
||||
}));
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
import {StringMap, StringMapWrapper, ListWrapper} from 'angular2/src/facade/collection';
|
||||
import {
|
||||
MessageBusSink,
|
||||
MessageBusSource,
|
||||
MessageBus
|
||||
} from 'angular2/src/web_workers/shared/message_bus';
|
||||
import {MockEventEmitter} from './mock_event_emitter';
|
||||
|
||||
/**
|
||||
* Returns two MessageBus instances that are attached to each other.
|
||||
* Such that whatever goes into one's sink comes out the others source.
|
||||
*/
|
||||
export function createPairedMessageBuses(): PairedMessageBuses {
|
||||
var firstChannels: StringMap<string, MockEventEmitter> = {};
|
||||
var workerMessageBusSink = new MockMessageBusSink(firstChannels);
|
||||
var uiMessageBusSource = new MockMessageBusSource(firstChannels);
|
||||
|
||||
var secondChannels: StringMap<string, MockEventEmitter> = {};
|
||||
var uiMessageBusSink = new MockMessageBusSink(secondChannels);
|
||||
var workerMessageBusSource = new MockMessageBusSource(secondChannels);
|
||||
|
||||
return new PairedMessageBuses(new MockMessageBus(uiMessageBusSink, uiMessageBusSource),
|
||||
new MockMessageBus(workerMessageBusSink, workerMessageBusSource));
|
||||
}
|
||||
|
||||
export class PairedMessageBuses {
|
||||
constructor(public ui: MessageBus, public worker: MessageBus) {}
|
||||
}
|
||||
|
||||
export class MockMessageBusSource implements MessageBusSource {
|
||||
constructor(private _channels: StringMap<string, MockEventEmitter>) {}
|
||||
|
||||
from(channel: string): MockEventEmitter {
|
||||
if (!StringMapWrapper.contains(this._channels, channel)) {
|
||||
this._channels[channel] = new MockEventEmitter();
|
||||
}
|
||||
return this._channels[channel];
|
||||
}
|
||||
}
|
||||
|
||||
export class MockMessageBusSink implements MessageBusSink {
|
||||
constructor(private _channels: StringMap<string, MockEventEmitter>) {}
|
||||
|
||||
to(channel: string): MockEventEmitter {
|
||||
if (!StringMapWrapper.contains(this._channels, channel)) {
|
||||
this._channels[channel] = new MockEventEmitter();
|
||||
}
|
||||
return this._channels[channel];
|
||||
}
|
||||
}
|
||||
|
||||
export class MockMessageBus extends MessageBus {
|
||||
constructor(public sink: MockMessageBusSink, public source: MockMessageBusSource) { super(); }
|
||||
|
||||
|
||||
to(channel: string): MockEventEmitter { return this.sink.to(channel); }
|
||||
|
||||
from(channel: string): MockEventEmitter { return this.source.from(channel); }
|
||||
}
|
||||
Reference in New Issue
Block a user