UNPKG

4.15 kBPlain TextView Raw
1import {isPresent, isBlank, Date, DateWrapper} from 'angular2/src/facade/lang';
2import {PromiseWrapper} from 'angular2/src/facade/async';
3import {bind, provide, Provider, OpaqueToken} from 'angular2/src/core/di';
4
5import {Metric} from './metric';
6import {Validator} from './validator';
7import {Reporter} from './reporter';
8import {WebDriverAdapter} from './web_driver_adapter';
9
10import {Options} from './common_options';
11import {MeasureValues} from './measure_values';
12
13/**
14 * The Sampler owns the sample loop:
15 * 1. calls the prepare/execute callbacks,
16 * 2. gets data from the metric
17 * 3. asks the validator for a valid sample
18 * 4. reports the new data to the reporter
19 * 5. loop until there is a valid sample
20 */
21export class Sampler {
22 // TODO(tbosch): use static values when our transpiler supports them
23 static get BINDINGS(): Provider[] { return _PROVIDERS; }
24
25 _driver: WebDriverAdapter;
26 _metric: Metric;
27 _reporter: Reporter;
28 _validator: Validator;
29 _prepare: Function;
30 _execute: Function;
31 _now: Function;
32
33 constructor({driver, metric, reporter, validator, prepare, execute, now}: {
34 driver?: WebDriverAdapter,
35 metric?: Metric,
36 reporter?: Reporter,
37 validator?: Validator,
38 prepare?: Function,
39 execute?: Function,
40 now?: Function
41 } = {}) {
42 this._driver = driver;
43 this._metric = metric;
44 this._reporter = reporter;
45 this._validator = validator;
46 this._prepare = prepare;
47 this._execute = execute;
48 this._now = now;
49 }
50
51 sample(): Promise<SampleState> {
52 var loop;
53 loop = (lastState) => {
54 return this._iterate(lastState).then((newState) => {
55 if (isPresent(newState.validSample)) {
56 return newState;
57 } else {
58 return loop(newState);
59 }
60 });
61 };
62 return loop(new SampleState([], null));
63 }
64
65 _iterate(lastState): Promise<SampleState> {
66 var resultPromise: Promise<any>;
67 if (isPresent(this._prepare)) {
68 resultPromise = this._driver.waitFor(this._prepare);
69 } else {
70 resultPromise = PromiseWrapper.resolve(null);
71 }
72 if (isPresent(this._prepare) || lastState.completeSample.length === 0) {
73 resultPromise = resultPromise.then((_) => this._metric.beginMeasure());
74 }
75 return resultPromise.then((_) => this._driver.waitFor(this._execute))
76 .then((_) => this._metric.endMeasure(isBlank(this._prepare)))
77 .then((measureValues) => this._report(lastState, measureValues));
78 }
79
80 _report(state: SampleState, metricValues: {[key: string]: any}): Promise<SampleState> {
81 var measureValues = new MeasureValues(state.completeSample.length, this._now(), metricValues);
82 var completeSample = state.completeSample.concat([measureValues]);
83 var validSample = this._validator.validate(completeSample);
84 var resultPromise = this._reporter.reportMeasureValues(measureValues);
85 if (isPresent(validSample)) {
86 resultPromise =
87 resultPromise.then((_) => this._reporter.reportSample(completeSample, validSample))
88 }
89 return resultPromise.then((_) => new SampleState(completeSample, validSample));
90 }
91}
92
93export class SampleState {
94 constructor(public completeSample: any[], public validSample: any[]) {}
95}
96
97var _PROVIDERS = [
98 bind(Sampler)
99 .toFactory((driver, metric, reporter, validator, prepare, execute, now) => new Sampler({
100 driver: driver,
101 reporter: reporter,
102 validator: validator,
103 metric: metric,
104 // TODO(tbosch): DI right now does not support null/undefined objects
105 // Mostly because the cache would have to be initialized with a
106 // special null object, which is expensive.
107 prepare: prepare !== false ? prepare : null,
108 execute: execute,
109 now: now
110 }),
111 [
112 WebDriverAdapter,
113 Metric,
114 Reporter,
115 Validator,
116 Options.PREPARE,
117 Options.EXECUTE,
118 Options.NOW
119 ])
120];