feat(benchpress): add a file reporter
This commit is contained in:
		
							parent
							
								
									146d731e73
								
							
						
					
					
						commit
						f9dcfa3ba5
					
				| @ -210,7 +210,13 @@ class DateWrapper { | |||||||
|   static DateTime fromMillis(int ms) { |   static DateTime fromMillis(int ms) { | ||||||
|     return new DateTime.fromMillisecondsSinceEpoch(ms); |     return new DateTime.fromMillisecondsSinceEpoch(ms); | ||||||
|   } |   } | ||||||
|  |   static int toMillis(DateTime date) { | ||||||
|  |     return date.millisecondsSinceEpoch; | ||||||
|  |   } | ||||||
|   static DateTime now() { |   static DateTime now() { | ||||||
|     return new DateTime.now(); |     return new DateTime.now(); | ||||||
|   } |   } | ||||||
|  |   static toJson(DateTime date) { | ||||||
|  |     return date.toUtc().toIso8601String(); | ||||||
|  |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -275,7 +275,13 @@ export class DateWrapper { | |||||||
|   static fromMillis(ms) { |   static fromMillis(ms) { | ||||||
|     return new Date(ms); |     return new Date(ms); | ||||||
|   } |   } | ||||||
|  |   static toMillis(date:Date) { | ||||||
|  |     return date.getTime(); | ||||||
|  |   } | ||||||
|   static now() { |   static now() { | ||||||
|     return new Date(); |     return new Date(); | ||||||
|   } |   } | ||||||
|  |   static toJson(date) { | ||||||
|  |     return date.toJSON(); | ||||||
|  |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,2 +1,24 @@ | |||||||
|  | import { bind } from 'angular2/di'; | ||||||
|  | import { JsonFileReporter } from './common'; | ||||||
|  | 
 | ||||||
| export * from './common'; | export * from './common'; | ||||||
| export { SeleniumWebDriverAdapter } from './src/webdriver/selenium_webdriver_adapter'; | export { SeleniumWebDriverAdapter } from './src/webdriver/selenium_webdriver_adapter'; | ||||||
|  | 
 | ||||||
|  | var fs = require('fs'); | ||||||
|  | 
 | ||||||
|  | // Note: Can't do the `require` call in a facade as it can't be loaded into the browser! | ||||||
|  | JsonFileReporter.BINDINGS.push( | ||||||
|  |   bind(JsonFileReporter.WRITE_FILE).toValue(writeFile) | ||||||
|  | ); | ||||||
|  | 
 | ||||||
|  | function writeFile(filename, content) { | ||||||
|  |   return new Promise(function(resolve, reject) { | ||||||
|  |     fs.writeFile(filename, content, (error) => { | ||||||
|  |       if (error) { | ||||||
|  |         reject(error); | ||||||
|  |       } else { | ||||||
|  |         resolve(); | ||||||
|  |       } | ||||||
|  |     }); | ||||||
|  |   }) | ||||||
|  | } | ||||||
|  | |||||||
| @ -7,6 +7,7 @@ export { WebDriverAdapter } from './src/web_driver_adapter'; | |||||||
| export { SizeValidator } from './src/validator/size_validator'; | export { SizeValidator } from './src/validator/size_validator'; | ||||||
| export { RegressionSlopeValidator } from './src/validator/regression_slope_validator'; | export { RegressionSlopeValidator } from './src/validator/regression_slope_validator'; | ||||||
| export { ConsoleReporter } from './src/reporter/console_reporter'; | export { ConsoleReporter } from './src/reporter/console_reporter'; | ||||||
|  | export { JsonFileReporter } from './src/reporter/json_file_reporter'; | ||||||
| export { SampleDescription } from './src/sample_description'; | export { SampleDescription } from './src/sample_description'; | ||||||
| export { PerflogMetric } from './src/metric/perflog_metric'; | export { PerflogMetric } from './src/metric/perflog_metric'; | ||||||
| export { ChromeDriverExtension } from './src/webdriver/chrome_driver_extension'; | export { ChromeDriverExtension } from './src/webdriver/chrome_driver_extension'; | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| import { Date } from 'angular2/src/facade/lang'; | import { Date, DateWrapper } from 'angular2/src/facade/lang'; | ||||||
| import { StringMap } from 'angular2/src/facade/collection'; | import { StringMap } from 'angular2/src/facade/collection'; | ||||||
| 
 | 
 | ||||||
| export class MeasureValues { | export class MeasureValues { | ||||||
| @ -11,4 +11,12 @@ export class MeasureValues { | |||||||
|     this.runIndex = runIndex; |     this.runIndex = runIndex; | ||||||
|     this.values = values; |     this.values = values; | ||||||
|   } |   } | ||||||
|  | 
 | ||||||
|  |   toJson() { | ||||||
|  |     return { | ||||||
|  |       'timeStamp': DateWrapper.toJson(this.timeStamp), | ||||||
|  |       'runIndex': this.runIndex, | ||||||
|  |       'values': this.values | ||||||
|  |     }; | ||||||
|  |   } | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										58
									
								
								modules/benchpress/src/reporter/json_file_reporter.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								modules/benchpress/src/reporter/json_file_reporter.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,58 @@ | |||||||
|  | import { DateWrapper, isPresent, isBlank, Json } from 'angular2/src/facade/lang'; | ||||||
|  | import { List } from 'angular2/src/facade/collection'; | ||||||
|  | import { Promise, PromiseWrapper } from 'angular2/src/facade/async'; | ||||||
|  | 
 | ||||||
|  | import { bind, OpaqueToken } from 'angular2/di'; | ||||||
|  | 
 | ||||||
|  | import { Reporter } from '../reporter'; | ||||||
|  | import { SampleDescription } from '../sample_description'; | ||||||
|  | import { MeasureValues } from '../measure_values'; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A reporter that writes results into a json file. | ||||||
|  |  * TODO(tbosch): right now we bind the `writeFile` method | ||||||
|  |  * in benchpres/benchpress.es6. This does not work for Dart, | ||||||
|  |  * find another way... | ||||||
|  |  */ | ||||||
|  | export class JsonFileReporter extends Reporter { | ||||||
|  |   // TODO(tbosch): use static values when our transpiler supports them
 | ||||||
|  |   static get WRITE_FILE() { return _WRITE_FILE; } | ||||||
|  |   // TODO(tbosch): use static values when our transpiler supports them
 | ||||||
|  |   static get PATH() { return _PATH; } | ||||||
|  |   static get BINDINGS() { return _BINDINGS; } | ||||||
|  | 
 | ||||||
|  |   _writeFile:Function; | ||||||
|  |   _path:string; | ||||||
|  |   _description:SampleDescription; | ||||||
|  | 
 | ||||||
|  |   constructor(sampleDescription, path, writeFile) { | ||||||
|  |     super(); | ||||||
|  |     this._description = sampleDescription; | ||||||
|  |     this._path = path; | ||||||
|  |     this._writeFile = writeFile; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   reportMeasureValues(measureValues:MeasureValues):Promise { | ||||||
|  |     return PromiseWrapper.resolve(null); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   reportSample(completeSample:List<MeasureValues>, validSample:List<MeasureValues>):Promise { | ||||||
|  |     var content = Json.stringify({ | ||||||
|  |       'description': this._description, | ||||||
|  |       'completeSample': completeSample, | ||||||
|  |       'validSample': validSample | ||||||
|  |     }); | ||||||
|  |     var filePath = `${this._path}/${this._description.id}_${DateWrapper.toMillis(DateWrapper.now())}.json`; | ||||||
|  |     return this._writeFile(filePath, content); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | var _WRITE_FILE = new OpaqueToken('JsonFileReporter.writeFile'); | ||||||
|  | var _PATH = new OpaqueToken('JsonFileReporter.path'); | ||||||
|  | var _BINDINGS = [ | ||||||
|  |   bind(JsonFileReporter).toFactory( | ||||||
|  |     (sampleDescription, path, writeFile) => new JsonFileReporter(sampleDescription, path, writeFile), | ||||||
|  |     [SampleDescription, _PATH, _WRITE_FILE] | ||||||
|  |   ), | ||||||
|  |   bind(_PATH).toValue('.') | ||||||
|  | ]; | ||||||
| @ -23,6 +23,14 @@ export class SampleDescription { | |||||||
|       StringMapWrapper.forEach(description, (value, prop) => this.description[prop] = value ); |       StringMapWrapper.forEach(description, (value, prop) => this.description[prop] = value ); | ||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
|  | 
 | ||||||
|  |   toJson() { | ||||||
|  |     return { | ||||||
|  |       'id': this.id, | ||||||
|  |       'description': this.description, | ||||||
|  |       'metrics': this.metrics | ||||||
|  |     }; | ||||||
|  |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| var _BINDINGS = [ | var _BINDINGS = [ | ||||||
|  | |||||||
							
								
								
									
										96
									
								
								modules/benchpress/test/reporter/json_file_reporter_spec.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								modules/benchpress/test/reporter/json_file_reporter_spec.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,96 @@ | |||||||
|  | import {describe, ddescribe, it, iit, xit, expect, beforeEach, afterEach} from 'angular2/test_lib'; | ||||||
|  | 
 | ||||||
|  | import { DateWrapper, Json, RegExpWrapper, isPresent } from 'angular2/src/facade/lang'; | ||||||
|  | import { PromiseWrapper } from 'angular2/src/facade/async'; | ||||||
|  | 
 | ||||||
|  | import { | ||||||
|  |   bind, Injector, | ||||||
|  |   SampleDescription, | ||||||
|  |   MeasureValues | ||||||
|  | } from 'benchpress/common'; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | import { JsonFileReporter } from 'benchpress/src/reporter/json_file_reporter'; | ||||||
|  | 
 | ||||||
|  | export function main() { | ||||||
|  |   describe('file reporter', () => { | ||||||
|  |     var loggedFile; | ||||||
|  | 
 | ||||||
|  |     function createReporter({sampleId, descriptions, metrics, path}) { | ||||||
|  |       var bindings = [ | ||||||
|  |         JsonFileReporter.BINDINGS, | ||||||
|  |         bind(SampleDescription).toValue(new SampleDescription(sampleId, descriptions, metrics)), | ||||||
|  |         bind(JsonFileReporter.PATH).toValue(path), | ||||||
|  |         bind(JsonFileReporter.WRITE_FILE).toValue((filename, content) => { | ||||||
|  |           loggedFile = { | ||||||
|  |             'filename': filename, | ||||||
|  |             'content': content | ||||||
|  |           }; | ||||||
|  |           return PromiseWrapper.resolve(null); | ||||||
|  |         }) | ||||||
|  |       ]; | ||||||
|  |       return new Injector(bindings).get(JsonFileReporter); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     it('should write all data into a file', (done) => { | ||||||
|  |       createReporter({ | ||||||
|  |         sampleId: 'someId', | ||||||
|  |         descriptions: [{ 'a': 2 }], | ||||||
|  |         path: 'somePath', | ||||||
|  |         metrics: { | ||||||
|  |           'script': 'script time' | ||||||
|  |         } | ||||||
|  |       }).reportSample([ | ||||||
|  |         mv(0, 0, { 'a': 3, 'b': 6}) | ||||||
|  |       ], [mv(0, 0, { | ||||||
|  |         'a': 3, 'b': 6 | ||||||
|  |       }), mv(1, 1, { | ||||||
|  |         'a': 5, 'b': 9 | ||||||
|  |       })]); | ||||||
|  |       var regExp = RegExpWrapper.create('somePath/someId_\\d+\\.json'); | ||||||
|  |       expect(isPresent(RegExpWrapper.firstMatch(regExp, loggedFile['filename']))).toBe(true); | ||||||
|  |       var parsedContent = Json.parse(loggedFile['content']); | ||||||
|  |       expect(parsedContent).toEqual({ | ||||||
|  |         "description": { | ||||||
|  |           "id": "someId", | ||||||
|  |           "description": { | ||||||
|  |             "a": 2 | ||||||
|  |           }, | ||||||
|  |           "metrics": {"script": "script time"} | ||||||
|  |         }, | ||||||
|  |         "completeSample": [{ | ||||||
|  |             "timeStamp": "1970-01-01T00:00:00.000Z", | ||||||
|  |             "runIndex": 0, | ||||||
|  |             "values": { | ||||||
|  |               "a": 3, | ||||||
|  |               "b": 6 | ||||||
|  |             } | ||||||
|  |         }], | ||||||
|  |         "validSample": [ | ||||||
|  |           { | ||||||
|  |             "timeStamp": "1970-01-01T00:00:00.000Z", | ||||||
|  |             "runIndex": 0, | ||||||
|  |             "values": { | ||||||
|  |               "a": 3, | ||||||
|  |               "b": 6 | ||||||
|  |             } | ||||||
|  |           }, | ||||||
|  |           { | ||||||
|  |             "timeStamp": "1970-01-01T00:00:00.001Z", | ||||||
|  |             "runIndex": 1, | ||||||
|  |             "values": { | ||||||
|  |               "a": 5, | ||||||
|  |               "b": 9 | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         ] | ||||||
|  |       }); | ||||||
|  |       done(); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |   }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function mv(runIndex, time, values) { | ||||||
|  |   return new MeasureValues(runIndex, DateWrapper.fromMillis(time), values); | ||||||
|  | } | ||||||
| @ -40,6 +40,7 @@ | |||||||
|     "dgeni": "^0.4.1", |     "dgeni": "^0.4.1", | ||||||
|     "dgeni-packages": "^0.10.10", |     "dgeni-packages": "^0.10.10", | ||||||
|     "event-stream": "^3.1.5", |     "event-stream": "^3.1.5", | ||||||
|  |     "fs-extra": "^0.16.4", | ||||||
|     "glob": "^4.0.6", |     "glob": "^4.0.6", | ||||||
|     "gulp": "^3.8.8", |     "gulp": "^3.8.8", | ||||||
|     "gulp-changed": "^1.0.0", |     "gulp-changed": "^1.0.0", | ||||||
|  | |||||||
| @ -1,5 +1,6 @@ | |||||||
| // load traceur runtime as our tests are written in es6
 | // load traceur runtime as our tests are written in es6
 | ||||||
| require('traceur/bin/traceur-runtime.js'); | require('traceur/bin/traceur-runtime.js'); | ||||||
|  | var fs = require('fs-extra'); | ||||||
| 
 | 
 | ||||||
| var argv = require('yargs') | var argv = require('yargs') | ||||||
|     .usage('Angular e2e/perf test options.') |     .usage('Angular e2e/perf test options.') | ||||||
| @ -208,13 +209,21 @@ exports.createBenchpressRunner = function(options) { | |||||||
|   if (process.env.GIT_SHA) { |   if (process.env.GIT_SHA) { | ||||||
|     runId = process.env.GIT_SHA + ' ' + runId; |     runId = process.env.GIT_SHA + ' ' + runId; | ||||||
|   } |   } | ||||||
|  |   var resultsFolder = './dist/benchmark_results'; | ||||||
|  |   fs.ensureDirSync(resultsFolder); | ||||||
|   var bindings = [ |   var bindings = [ | ||||||
|     benchpress.SeleniumWebDriverAdapter.PROTRACTOR_BINDINGS, |     benchpress.SeleniumWebDriverAdapter.PROTRACTOR_BINDINGS, | ||||||
|     benchpress.bind(benchpress.Options.FORCE_GC).toValue(argv['force-gc']), |     benchpress.bind(benchpress.Options.FORCE_GC).toValue(argv['force-gc']), | ||||||
|     benchpress.bind(benchpress.Options.DEFAULT_DESCRIPTION).toValue({ |     benchpress.bind(benchpress.Options.DEFAULT_DESCRIPTION).toValue({ | ||||||
|       'lang': options.lang, |       'lang': options.lang, | ||||||
|       'runId': runId |       'runId': runId | ||||||
|     }) |     }), | ||||||
|  |     benchpress.MultiReporter.createBindings([ | ||||||
|  |       benchpress.ConsoleReporter, | ||||||
|  |       benchpress.JsonFileReporter | ||||||
|  |     ]), | ||||||
|  |     benchpress.JsonFileReporter.BINDINGS, | ||||||
|  |     benchpress.bind(benchpress.JsonFileReporter.PATH).toValue(resultsFolder) | ||||||
|   ]; |   ]; | ||||||
|   if (argv['benchmark']) { |   if (argv['benchmark']) { | ||||||
|     bindings.push(benchpress.Validator.bindTo(benchpress.RegressionSlopeValidator)); |     bindings.push(benchpress.Validator.bindTo(benchpress.RegressionSlopeValidator)); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user