Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion modules/angular2/src/facade/lang.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
library angular.core.facade.lang;

export 'dart:core' show Type, RegExp, print;
export 'dart:core' show Type, RegExp, print, DateTime;
import 'dart:math' as math;
import 'dart:convert' as convert;

Expand Down Expand Up @@ -183,3 +183,12 @@ class Json {
static parse(String s) => convert.JSON.decode(s);
static stringify(data) => convert.JSON.encode(data);
}

class DateWrapper {
static fromMillis(int ms) {
return new DateTime.fromMillisecondsSinceEpoch(ms);
}
static now() {
return new DateTime.now();
}
}
10 changes: 10 additions & 0 deletions modules/angular2/src/facade/lang.es6
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export {_global as global};

export var Type = Function;
export var Math = _global.Math;
export var Date = _global.Date;

var assertionsEnabled_ = typeof assert !== 'undefined';

Expand Down Expand Up @@ -250,3 +251,12 @@ export function print(obj) {

// Can't be all uppercase as our transpiler would think it is a special directive...
export var Json = _global.JSON;

export class DateWrapper {
static fromMillis(ms) {
return new Date(ms);
}
static now() {
return new Date();
}
}
70 changes: 68 additions & 2 deletions modules/angular2/src/test_lib/test_lib.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import 'dart:async';
import 'package:angular2/src/reflection/reflection.dart';
import 'package:angular2/src/facade/dom.dart';
import 'package:angular2/src/reflection/reflection_capabilities.dart';
import 'package:collection/equality.dart';

bool IS_DARTIUM = true;

Expand All @@ -22,7 +23,9 @@ class Expect extends gns.Expect {

NotExpect get not => new NotExpect(actual);

void toEqual(expected) => toHaveSameProps(expected);
// TODO(tbosch) change back when https://github.com/vsavkin/guinness/issues/41 is fixed
// void toEqual(expected) => toHaveSameProps(expected);
void toEqual(expected) => _expect(actual, new FixedSamePropsMatcher(expected));
void toThrowError([message=""]) => this.toThrowWith(message: message);
void toBePromise() => _expect(actual is Future, equals(true));
void toImplement(expected) => toBeA(expected);
Expand All @@ -33,7 +36,10 @@ class Expect extends gns.Expect {
class NotExpect extends gns.NotExpect {
NotExpect(actual) : super(actual);

void toEqual(expected) => toHaveSameProps(expected);
// TODO(tbosch) change back when https://github.com/vsavkin/guinness/issues/41 is fixed
// void toEqual(expected) => toHaveSameProps(expected);
void toEqual(expected) => _expect(actual, isNot(new FixedSamePropsMatcher(expected)));
Function get _expect => gns.guinness.matchers.expect;
}

beforeEach(fn) {
Expand Down Expand Up @@ -70,4 +76,64 @@ _handleAsync(fn) {
}

return fn;
}

// TODO(tbosch): remove when https://github.com/vsavkin/guinness/issues/41
// is fixed
class FixedSamePropsMatcher extends Matcher {
final Object _expected;

const FixedSamePropsMatcher(this._expected);

bool matches(actual, Map matchState) {
return compare(toData(_expected), toData(actual));
}

Description describeMismatch(item, Description mismatchDescription,
Map matchState, bool verbose) =>
mismatchDescription.add('is equal to ${toData(item)}. Expected: ${toData(_expected)}');

Description describe(Description description) =>
description.add('has different properties');

toData(obj) => new _FixedObjToData().call(obj);
compare(d1, d2) => new DeepCollectionEquality().equals(d1, d2);
}

// TODO(tbosch): remove when https://github.com/vsavkin/guinness/issues/41
// is fixed
class _FixedObjToData {
final visitedObjects = new Set();

call(obj) {
if (visitedObjects.contains(obj)) return null;
visitedObjects.add(obj);

if (obj is num || obj is String || obj is bool) return obj;
if (obj is Iterable) return obj.map(call).toList();
if (obj is Map) return mapToData(obj);
return toDataUsingReflection(obj);
}

mapToData(obj) {
var res = {};
obj.forEach((k,v) {
res[call(k)] = call(v);
});
return res;
}

toDataUsingReflection(obj) {
final clazz = reflectClass(obj.runtimeType);
final instance = reflect(obj);

return clazz.declarations.values.fold({}, (map, decl) {
if (decl is VariableMirror && !decl.isPrivate && !decl.isStatic) {
final field = instance.getField(decl.simpleName);
final name = MirrorSystem.getName(decl.simpleName);
map[name] = call(field.reflectee);
}
return map;
});
}
}
6 changes: 5 additions & 1 deletion modules/angular2/test/test_lib/test_lib_spec.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {describe, it, iit, ddescribe, expect, tick, async, SpyObject, beforeEach, proxy} from 'angular2/test_lib';
import {MapWrapper, ListWrapper} from 'angular2/src/facade/collection';
import {PromiseWrapper} from 'angular2/src/facade/async';
import {IMPLEMENTS} from 'angular2/src/facade/lang';
import {IMPLEMENTS, Date, DateWrapper} from 'angular2/src/facade/lang';

class TestObj {
prop;
Expand All @@ -26,6 +26,10 @@ export function main() {
expect(falseActual).not.toEqual(expected);
});

it('should structurally compare objects with private and static fields', () => {
expect(DateWrapper.fromMillis(1)).toEqual(DateWrapper.fromMillis(1));
});

it('should work for arrays of string maps', () => {
expect([{'a':'b'}]).toEqual([{'a':'b'}]);
});
Expand Down
1 change: 1 addition & 0 deletions modules/benchpress/benchpress.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ export { PerflogMetric } from './src/metric/perflog_metric';
export { ChromeDriverExtension } from './src/webdriver/chrome_driver_extension';
export { Runner } from './src/runner';
export { Options } from './src/sample_options';
export { MeasureValues } from './src/measure_values';

export { bind, Injector, OpaqueToken } from 'angular2/di';
13 changes: 13 additions & 0 deletions modules/benchpress/src/measure_values.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Date } from 'angular2/src/facade/lang';

export class MeasureValues {
timeStamp:Date;
runIndex:number;
values:any;

constructor(runIndex:number, timeStamp:Date, values:any) {
this.timeStamp = timeStamp;
this.runIndex = runIndex;
this.values = values;
}
}
6 changes: 4 additions & 2 deletions modules/benchpress/src/reporter.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,18 @@ import {
ABSTRACT, BaseException
} from 'angular2/src/facade/lang';

import { MeasureValues } from './measure_values';

/**
* A reporter reports measure values and the valid sample.
*/
@ABSTRACT()
export class Reporter {
reportMeasureValues(index:number, values:any):Promise {
reportMeasureValues(values:MeasureValues):Promise {
throw new BaseException('NYI');
}

reportSample(completeSample:List, validSample:List):Promise {
reportSample(completeSample:List<MeasureValues>, validSample:List<MeasureValues>):Promise {
throw new BaseException('NYI');
}
}
9 changes: 5 additions & 4 deletions modules/benchpress/src/reporter/console_reporter.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { bind, OpaqueToken } from 'angular2/di';
import { Statistic } from '../statistic';
import { Reporter } from '../reporter';
import { SampleDescription } from '../sample_description';
import { MeasureValues } from '../measure_values';

/**
* A reporter for the console
Expand Down Expand Up @@ -72,20 +73,20 @@ export class ConsoleReporter extends Reporter {
this._printStringRow(this._metricNames.map( (_) => '' ), '-');
}

reportMeasureValues(index:number, measuredValues:any):Promise {
reportMeasureValues(measureValues:MeasureValues):Promise {
var formattedValues = ListWrapper.map(this._metricNames, (metricName) => {
var value = measuredValues[metricName];
var value = measureValues.values[metricName];
return ConsoleReporter._formatNum(value);
});
this._printStringRow(formattedValues);
return PromiseWrapper.resolve(null);
}

reportSample(completeSample:List, validSample:List):Promise {
reportSample(completeSample:List<MeasureValues>, validSample:List<MeasureValues>):Promise {
this._printStringRow(this._metricNames.map( (_) => '' ), '=');
this._printStringRow(
ListWrapper.map(this._metricNames, (metricName) => {
var sample = ListWrapper.map(validSample, (measuredValues) => measuredValues[metricName]);
var sample = ListWrapper.map(validSample, (measureValues) => measureValues.values[metricName]);
var mean = Statistic.calculateMean(sample);
var cv = Statistic.calculateCoefficientOfVariation(sample, mean);
return `${ConsoleReporter._formatNum(mean)}\u00B1${Math.floor(cv)}%`;
Expand Down
30 changes: 20 additions & 10 deletions modules/benchpress/src/sampler.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { isPresent, isBlank } from 'angular2/src/facade/lang';
import { isPresent, isBlank, Date, DateWrapper } from 'angular2/src/facade/lang';
import { Promise, PromiseWrapper } from 'angular2/src/facade/async';
import { StringMapWrapper, List, ListWrapper } from 'angular2/src/facade/collection';
import { bind, OpaqueToken } from 'angular2/di';
Expand All @@ -10,6 +10,7 @@ import { WebDriverExtension } from './web_driver_extension';
import { WebDriverAdapter } from './web_driver_adapter';

import { Options } from './sample_options';
import { MeasureValues} from './measure_values';

/**
* The Sampler owns the sample loop:
Expand All @@ -22,6 +23,8 @@ import { Options } from './sample_options';
export class Sampler {
// TODO(tbosch): use static values when our transpiler supports them
static get BINDINGS() { return _BINDINGS; }
// TODO(tbosch): use static values when our transpiler supports them
static get TIME() { return _TIME; }

_driver:WebDriverAdapter;
_driverExtension:WebDriverExtension;
Expand All @@ -31,13 +34,14 @@ export class Sampler {
_forceGc:boolean;
_prepare:Function;
_execute:Function;
_time:Function;

constructor({
driver, driverExtension, metric, reporter, validator, forceGc, prepare, execute
driver, driverExtension, metric, reporter, validator, forceGc, prepare, execute, time
}:{
driver: WebDriverAdapter,
driverExtension: WebDriverExtension, metric: Metric, reporter: Reporter,
validator: Validator, prepare: Function, execute: Function
validator: Validator, prepare: Function, execute: Function, time: Function
}={}) {
this._driver = driver;
this._driverExtension = driverExtension;
Expand All @@ -47,6 +51,7 @@ export class Sampler {
this._forceGc = forceGc;
this._prepare = prepare;
this._execute = execute;
this._time = time;
}

sample():Promise<SampleState> {
Expand Down Expand Up @@ -90,10 +95,11 @@ export class Sampler {
.then( (measureValues) => this._report(lastState, measureValues) );
}

_report(state:SampleState, measuredValues:any):Promise<SampleState> {
var completeSample = ListWrapper.concat(state.completeSample, [measuredValues]);
_report(state:SampleState, metricValues:any):Promise<SampleState> {
var measureValues = new MeasureValues(state.completeSample.length, this._time(), metricValues);
var completeSample = ListWrapper.concat(state.completeSample, [measureValues]);
var validSample = this._validator.validate(completeSample);
var resultPromise = this._reporter.reportMeasureValues(completeSample.length - 1, measuredValues);
var resultPromise = this._reporter.reportMeasureValues(measureValues);
if (isPresent(validSample)) {
resultPromise = resultPromise.then( (_) => this._reporter.reportSample(completeSample, validSample) )
}
Expand All @@ -112,9 +118,11 @@ export class SampleState {
}
}

var _TIME = new OpaqueToken('Sampler.time');

var _BINDINGS = [
bind(Sampler).toFactory(
(driver, driverExtension, metric, reporter, validator, forceGc, prepare, execute) => new Sampler({
(driver, driverExtension, metric, reporter, validator, forceGc, prepare, execute, time) => new Sampler({
driver: driver,
driverExtension: driverExtension,
reporter: reporter,
Expand All @@ -125,10 +133,12 @@ var _BINDINGS = [
// Mostly because the cache would have to be initialized with a
// special null object, which is expensive.
prepare: prepare !== false ? prepare : null,
execute: execute
execute: execute,
time: time
}),
[WebDriverAdapter, WebDriverExtension, Metric, Reporter, Validator, Options.FORCE_GC, Options.PREPARE, Options.EXECUTE]
[WebDriverAdapter, WebDriverExtension, Metric, Reporter, Validator, Options.FORCE_GC, Options.PREPARE, Options.EXECUTE, _TIME]
),
bind(Options.FORCE_GC).toValue(false),
bind(Options.PREPARE).toValue(false)
bind(Options.PREPARE).toValue(false),
bind(_TIME).toValue( () => DateWrapper.now() )
];
4 changes: 3 additions & 1 deletion modules/benchpress/src/validator.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import {
ABSTRACT, BaseException
} from 'angular2/src/facade/lang';

import { MeasureValues } from './measure_values';

/**
* A Validator calculates a valid sample out of the complete sample.
* A valid sample is a sample that represents the population that should be observed
Expand All @@ -13,7 +15,7 @@ export class Validator {
/**
* Calculates a valid sample out of the complete sample
*/
validate(completeSample:List<any>):List<any> {
validate(completeSample:List<MeasureValues>):List<MeasureValues> {
throw new BaseException('NYI');
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { bind, OpaqueToken } from 'angular2/di';

import { Validator } from '../validator';
import { Statistic } from '../statistic';
import { MeasureValues } from '../measure_values';

/**
* A validator that checks the regression slope of a specific metric.
Expand Down Expand Up @@ -32,7 +33,7 @@ export class RegressionSlopeValidator extends Validator {
};
}

validate(completeSample:List<any>):List<any> {
validate(completeSample:List<MeasureValues>):List<MeasureValues> {
if (completeSample.length >= this._sampleSize) {
var latestSample =
ListWrapper.slice(completeSample, completeSample.length - this._sampleSize, completeSample.length);
Expand All @@ -42,7 +43,7 @@ export class RegressionSlopeValidator extends Validator {
// For now, we only use the array index as x value.
// TODO(tbosch): think about whether we should use time here instead
ListWrapper.push(xValues, i);
ListWrapper.push(yValues, latestSample[i][this._metric]);
ListWrapper.push(yValues, latestSample[i].values[this._metric]);
}
var regressionSlope = Statistic.calculateRegressionSlope(
xValues, Statistic.calculateMean(xValues),
Expand Down
Loading